Skip to content

Commit 9bc581a

Browse files
committed
Add more examples: UDP and data pipe.
1 parent 186345a commit 9bc581a

File tree

24 files changed

+1136
-109
lines changed

24 files changed

+1136
-109
lines changed

README.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,14 @@ Simple function definitions.
7676
7777
```cpp
7878
void FreeFunc(int value) {
79-
cout << "FreeFuncInt " << value << endl;
79+
cout << "FreeFuncInt " << value << endl;
8080
}
8181
8282
class TestClass {
8383
public:
84-
void MemberFunc(int value) {
85-
cout << "MemberFunc " << value << endl;
86-
}
84+
void MemberFunc(int value) {
85+
cout << "MemberFunc " << value << endl;
86+
}
8787
};
8888
```
8989

@@ -368,23 +368,23 @@ void TestAllTargetTypes() {
368368
void SysDataNoLock::SetSystemModeAsyncAPI(SystemMode::Type systemMode)
369369
{
370370
// Is the caller executing on workerThread2?
371-
if (workerThread2.GetThreadId() != Thread::GetCurrentThreadId())
372-
{
373-
// Create an asynchronous delegate and re-invoke the function call on workerThread2
374-
MakeDelegate(this, &SysDataNoLock::SetSystemModeAsyncAPI, workerThread2).AsyncInvoke(systemMode);
375-
return;
376-
}
377-
378-
// Create the callback data
379-
SystemModeChanged callbackData;
380-
callbackData.PreviousSystemMode = m_systemMode;
381-
callbackData.CurrentSystemMode = systemMode;
382-
383-
// Update the system mode
384-
m_systemMode = systemMode;
385-
386-
// Callback all registered subscribers
387-
SystemModeChangedDelegate(callbackData);
371+
if (workerThread2.GetThreadId() != Thread::GetCurrentThreadId())
372+
{
373+
// Create an asynchronous delegate and re-invoke the function call on workerThread2
374+
MakeDelegate(this, &SysDataNoLock::SetSystemModeAsyncAPI, workerThread2).AsyncInvoke(systemMode);
375+
return;
376+
}
377+
378+
// Create the callback data
379+
SystemModeChanged callbackData;
380+
callbackData.PreviousSystemMode = m_systemMode;
381+
callbackData.CurrentSystemMode = systemMode;
382+
383+
// Update the system mode
384+
m_systemMode = systemMode;
385+
386+
// Callback all registered subscribers
387+
SystemModeChangedDelegate(callbackData);
388388
}
389389
```
390390

docs/DETAILS.md

Lines changed: 97 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ The C++ delegates library can invoke any callable function synchronously, asynch
2020
- [Build Options](#build-options)
2121
- [Example Projects](#example-projects)
2222
- [`bare-metal`](#bare-metal)
23+
- [`win32-pipe-serializer`](#win32-pipe-serializer)
24+
- [`win32-upd-serializer`](#win32-upd-serializer)
2325
- [`zeromq-serializer`](#zeromq-serializer)
2426
- [`zeromq-msgpack-cpp`](#zeromq-msgpack-cpp)
2527
- [`system-architecture`](#system-architecture)
@@ -201,7 +203,25 @@ Remote delegate example with no external libraries.
201203
| Interface | Implementation |
202204
| --- | --- |
203205
| `ISerializer` | Insertion `operator<<` and extraction `operator>>` operators.
204-
| `IDispatcher` | Shared sender/receiver `std::stringstream`.
206+
| `IDispatcher` | Shared sender/receiver `std::stringstream` for dispatcher transport.
207+
208+
### `win32-pipe-serializer`
209+
210+
Remote delegate example with Windows pipe and `serialize`.
211+
212+
| Interface | Implementation |
213+
| --- | --- |
214+
| `ISerializer` | `serialize` class.
215+
| `IDispatcher` | Windows data pipe for dispatcher transport.
216+
217+
### `win32-upd-serializer`
218+
219+
Remote delegate example with Windows UDP socket and `serialize`.
220+
221+
| Interface | Implementation |
222+
| --- | --- |
223+
| `ISerializer` | `serialize` class.
224+
| `IDispatcher` | Windows UDP socket for dispatcher transport.
205225
206226
### `zeromq-serializer`
207227
@@ -210,7 +230,7 @@ Remote delegate example using ZeroMQ and `serialize`.
210230
| Interface | Implementation |
211231
| --- | --- |
212232
| `ISerializer` | `serialize` class.
213-
| `IDispatcher` | ZeroMQ library.
233+
| `IDispatcher` | ZeroMQ library for dispatcher transport.
214234
215235
### `zeromq-msgpack-cpp`
216236
@@ -219,7 +239,7 @@ Remote delegate example using ZeroMQ and MessagePack libraries.
219239
| Interface | Implementation |
220240
| --- | --- |
221241
| `ISerializer` | MessagePack library.
222-
| `IDispatcher` | ZeroMQ library.
242+
| `IDispatcher` | ZeroMQ library for dispatcher transport.
223243
224244
### `system-architecture`
225245
@@ -228,7 +248,7 @@ Remote delegate example showing a complex system architecture using ZeroMQ and M
228248
| Interface | Implementation |
229249
| --- | --- |
230250
| `ISerializer` | MessagePack library. |
231-
| `IDispatcher` | ZeroMQ library. |
251+
| `IDispatcher` | ZeroMQ library for dispatcher transport. |
232252
233253
# DelegateMQ Dependencies
234254
@@ -887,17 +907,17 @@ The `IThread` interface is used to send a delegate and argument data through a m
887907
class IThread
888908
{
889909
public:
890-
/// Destructor
891-
virtual ~IThread() = default;
892-
893-
/// Dispatch a DelegateMsg onto this thread. The implementer is responsible
894-
/// for getting the DelegateMsg into an OS message queue. Once DelegateMsg
895-
/// is on the correct thread of control, the DelegateInvoker::Invoke() function
896-
/// must be called to execute the delegate.
897-
/// @param[in] msg - a pointer to the delegate message that must be created dynamically.
898-
/// @pre Caller *must* create the DelegateMsg argument dynamically.
899-
/// @post The destination thread calls Invoke().
900-
virtual void DispatchDelegate(std::shared_ptr<DelegateMsg> msg) = 0;
910+
/// Destructor
911+
virtual ~IThread() = default;
912+
913+
/// Dispatch a DelegateMsg onto this thread. The implementer is responsible
914+
/// for getting the DelegateMsg into an OS message queue. Once DelegateMsg
915+
/// is on the correct thread of control, the DelegateInvoker::Invoke() function
916+
/// must be called to execute the delegate.
917+
/// @param[in] msg - a pointer to the delegate message that must be created dynamically.
918+
/// @pre Caller *must* create the DelegateMsg argument dynamically.
919+
/// @post The destination thread calls Invoke().
920+
virtual void DispatchDelegate(std::shared_ptr<DelegateMsg> msg) = 0;
901921
};
902922
```
903923

@@ -919,16 +939,16 @@ if (thread) {
919939
```cpp
920940
void Thread::DispatchDelegate(std::shared_ptr<DelegateMQ::DelegateMsg> msg)
921941
{
922-
if (m_thread == nullptr)
923-
throw std::invalid_argument("Thread pointer is null");
942+
if (m_thread == nullptr)
943+
throw std::invalid_argument("Thread pointer is null");
924944

925-
// Create a new ThreadMsg
945+
// Create a new ThreadMsg
926946
std::shared_ptr<ThreadMsg> threadMsg(new ThreadMsg(MSG_DISPATCH_DELEGATE, msg));
927947

928-
// Add dispatch delegate msg to queue and notify worker thread
929-
std::unique_lock<std::mutex> lk(m_mutex);
930-
m_queue.push(threadMsg);
931-
m_cv.notify_one();
948+
// Add dispatch delegate msg to queue and notify worker thread
949+
std::unique_lock<std::mutex> lk(m_mutex);
950+
m_queue.push(threadMsg);
951+
m_cv.notify_one();
932952
}
933953
```
934954
@@ -946,10 +966,10 @@ void Thread::DispatchDelegate(std::shared_ptr<DelegateMQ::DelegateMsg> msg)
946966
class IDelegateInvoker
947967
{
948968
public:
949-
/// Called to invoke the bound target function by the destination thread of control.
950-
/// @param[in] msg - the incoming delegate message.
951-
/// @return `true` if function was invoked; `false` if failed.
952-
virtual bool Invoke(std::shared_ptr<DelegateMsg> msg) = 0;
969+
/// Called to invoke the bound target function by the destination thread of control.
970+
/// @param[in] msg - the incoming delegate message.
971+
/// @return `true` if function was invoked; `false` if failed.
972+
virtual bool Invoke(std::shared_ptr<DelegateMsg> msg) = 0;
953973
};
954974
```
955975

@@ -958,57 +978,57 @@ The `Thread::Process()` thread loop is shown below. `Invoke()` is called for eac
958978
```cpp
959979
void Thread::Process()
960980
{
961-
m_timerExit = false;
962-
std::thread timerThread(&Thread::TimerThread, this);
963-
964-
while (1)
965-
{
966-
std::shared_ptr<ThreadMsg> msg;
967-
{
968-
// Wait for a message to be added to the queue
969-
std::unique_lock<std::mutex> lk(m_mutex);
970-
while (m_queue.empty())
971-
m_cv.wait(lk);
972-
973-
if (m_queue.empty())
974-
continue;
975-
976-
msg = m_queue.front();
977-
m_queue.pop();
978-
}
979-
980-
switch (msg->GetId())
981-
{
982-
case MSG_DISPATCH_DELEGATE:
983-
{
984-
// Get pointer to DelegateMsg data from queue msg data
985-
auto delegateMsg = msg->GetData();
986-
ASSERT_TRUE(delegateMsg);
987-
988-
auto invoker = delegateMsg->GetDelegateInvoker();
989-
ASSERT_TRUE(invoker);
990-
991-
// Invoke the delegate destination target function
992-
bool success = invoker->Invoke(delegateMsg);
993-
ASSERT_TRUE(success);
994-
break;
995-
}
996-
997-
case MSG_TIMER:
998-
Timer::ProcessTimers();
999-
break;
1000-
1001-
case MSG_EXIT_THREAD:
1002-
{
1003-
m_timerExit = true;
1004-
timerThread.join();
1005-
return;
1006-
}
1007-
1008-
default:
1009-
throw std::invalid_argument("Invalid message ID");
1010-
}
1011-
}
981+
m_timerExit = false;
982+
std::thread timerThread(&Thread::TimerThread, this);
983+
984+
while (1)
985+
{
986+
std::shared_ptr<ThreadMsg> msg;
987+
{
988+
// Wait for a message to be added to the queue
989+
std::unique_lock<std::mutex> lk(m_mutex);
990+
while (m_queue.empty())
991+
m_cv.wait(lk);
992+
993+
if (m_queue.empty())
994+
continue;
995+
996+
msg = m_queue.front();
997+
m_queue.pop();
998+
}
999+
1000+
switch (msg->GetId())
1001+
{
1002+
case MSG_DISPATCH_DELEGATE:
1003+
{
1004+
// Get pointer to DelegateMsg data from queue msg data
1005+
auto delegateMsg = msg->GetData();
1006+
ASSERT_TRUE(delegateMsg);
1007+
1008+
auto invoker = delegateMsg->GetDelegateInvoker();
1009+
ASSERT_TRUE(invoker);
1010+
1011+
// Invoke the delegate destination target function
1012+
bool success = invoker->Invoke(delegateMsg);
1013+
ASSERT_TRUE(success);
1014+
break;
1015+
}
1016+
1017+
case MSG_TIMER:
1018+
Timer::ProcessTimers();
1019+
break;
1020+
1021+
case MSG_EXIT_THREAD:
1022+
{
1023+
m_timerExit = true;
1024+
timerThread.join();
1025+
return;
1026+
}
1027+
1028+
default:
1029+
throw std::invalid_argument("Invalid message ID");
1030+
}
1031+
}
10121032
}
10131033
```
10141034

example/sample-projects/system-architecture/client/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ include("${CMAKE_SOURCE_DIR}/../../../../Config.cmake")
1111
# Set delegate library build options
1212
add_compile_definitions(THREAD_STDLIB)
1313
add_compile_definitions(SERIALIZE_MSGPACK)
14-
add_compile_definitions(TRANSPORT_MSGPACK)
14+
add_compile_definitions(TRANSPORT_ZEROMQ)
1515

1616
# Collect all .cpp and *.h source files in the src directory
1717
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp" "${CMAKE_SOURCE_DIR}/*.h")

example/sample-projects/system-architecture/server/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ include("${CMAKE_SOURCE_DIR}/../../../../Config.cmake")
1111
# Set delegate library build options
1212
add_compile_definitions(THREAD_STDLIB)
1313
add_compile_definitions(SERIALIZE_MSGPACK)
14-
add_compile_definitions(TRANSPORT_MSGPACK)
14+
add_compile_definitions(TRANSPORT_ZEROMQ)
1515

1616
# Collect all .cpp and *.h source files in the src directory
1717
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp" "${CMAKE_SOURCE_DIR}/*.h")
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Specify the minimum CMake version required
2+
cmake_minimum_required(VERSION 3.10)
3+
4+
set (DELEGATE_APP "delegate_app")
5+
project(Delegate VERSION 1.0 LANGUAGES CXX)
6+
add_compile_definitions(SERVER_APP)
7+
8+
include("${CMAKE_SOURCE_DIR}/../../../Config.cmake")
9+
10+
# Set delegate library build options
11+
add_compile_definitions(THREAD_STDLIB)
12+
add_compile_definitions(SERIALIZE_SERIALIZE)
13+
add_compile_definitions(TRANSPORT_WIN32_PIPE)
14+
15+
# Collect all .cpp and *.h source files in the src directory
16+
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp" "${CMAKE_SOURCE_DIR}/*.h")
17+
18+
# Collect all header files in the delegate directory
19+
file(GLOB Delegate_HEADERS
20+
"${DELEGATE_ROOT_DIR}/src/delegate-mq/*.h"
21+
"${DELEGATE_ROOT_DIR}/src/delegate-mq/delegate/*.h"
22+
)
23+
24+
# Organize delegate headers into a "Delegate Files" folder in Visual Studio
25+
source_group("Delegate Files" FILES ${Delegate_HEADERS})
26+
27+
# Add subdirectories to include path
28+
include_directories(
29+
${DELEGATE_ROOT_DIR}/src/delegate-mq
30+
)
31+
32+
# Add an executable target
33+
add_executable(${DELEGATE_APP} ${SOURCES} ${Delegate_HEADERS})
34+
35+
# Link the library directory
36+
link_directories(${DELEGATE_LIB_DIR})
37+
38+
# Link against the pre-built delegate_mq.lib
39+
target_link_libraries(${DELEGATE_APP} PRIVATE
40+
${DELEGATE_LIB_DIR}/${DELEGATE_LIB_NAME}
41+
)
42+

0 commit comments

Comments
 (0)