summaryrefslogtreecommitdiffstats
path: root/src/ml/dlib/examples/pipe_ex_2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ml/dlib/examples/pipe_ex_2.cpp')
-rw-r--r--src/ml/dlib/examples/pipe_ex_2.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/ml/dlib/examples/pipe_ex_2.cpp b/src/ml/dlib/examples/pipe_ex_2.cpp
new file mode 100644
index 000000000..53998dbe8
--- /dev/null
+++ b/src/ml/dlib/examples/pipe_ex_2.cpp
@@ -0,0 +1,160 @@
+// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
+
+
+/*
+ This is an example showing how to use the type_safe_union and pipe object from
+ from the dlib C++ Library to send messages between threads.
+
+ In this example we will create a class with a single thread in it. This thread
+ will receive messages from a pipe object and simply print them to the screen.
+ The interesting thing about this example is that it shows how to use a pipe and
+ type_safe_union to create a message channel between threads that can send many
+ different types of objects in a type safe manner.
+
+
+
+ Program output:
+ got a float: 4.567
+ got a string: string message
+ got an int: 7
+ got a string: yet another string message
+*/
+
+
+#include <dlib/threads.h>
+#include <dlib/pipe.h>
+#include <dlib/type_safe_union.h>
+#include <iostream>
+
+using namespace dlib;
+using namespace std;
+
+// ----------------------------------------------------------------------------------------
+
+typedef type_safe_union<int, float, std::string> tsu_type;
+/* This is a typedef for the type_safe_union we will be using in this example.
+ This type_safe_union object is a type-safe analogue of a union declared as follows:
+ union our_union_type
+ {
+ int a;
+ float b;
+ std::string c;
+ };
+
+ Note that the above union isn't actually valid C++ code because it contains a
+ non-POD type. That is, you can't put a std::string or any non-trivial
+ C++ class in a union. The type_safe_union, however, enables you to store non-POD
+ types such as the std::string.
+
+*/
+
+// ----------------------------------------------------------------------------------------
+
+class pipe_example : private threaded_object
+{
+public:
+ pipe_example(
+ ) :
+ message_pipe(4) // This 4 here is the size of our message_pipe. The significance is that
+ // if you try to enqueue more than 4 messages onto the pipe then enqueue() will
+ // block until there is room.
+ {
+ // start the thread
+ start();
+ }
+
+ ~pipe_example (
+ )
+ {
+ // wait for all the messages to be processed
+ message_pipe.wait_until_empty();
+
+ // Now disable the message_pipe. Doing this will cause all calls to
+ // message_pipe.dequeue() to return false so our thread will terminate
+ message_pipe.disable();
+
+ // now block until our thread has terminated
+ wait();
+ }
+
+ // Here we declare our pipe object. It will contain our messages.
+ dlib::pipe<tsu_type> message_pipe;
+
+private:
+
+ // When we call apply_to_contents() below these are the
+ // functions which get called.
+ void operator() (int val)
+ {
+ cout << "got an int: " << val << endl;
+ }
+
+ void operator() (float val)
+ {
+ cout << "got a float: " << val << endl;
+ }
+
+ void operator() (std::string val)
+ {
+ cout << "got a string: " << val << endl;
+ }
+
+ void thread ()
+ {
+ tsu_type msg;
+
+ // Here we loop on messages from the message_pipe.
+ while (message_pipe.dequeue(msg))
+ {
+ // Here we call the apply_to_contents() function on our type_safe_union.
+ // It takes a function object and applies that function object
+ // to the contents of the union. In our case we have setup
+ // the pipe_example class as our function object and so below we
+ // tell the msg object to take whatever it contains and
+ // call (*this)(contained_object); So what happens here is
+ // one of the three above functions gets called with the message
+ // we just got.
+ msg.apply_to_contents(*this);
+ }
+ }
+
+ // Finally, note that since we declared the operator() member functions
+ // private we need to declare the type_safe_union as a friend of this
+ // class so that it will be able to call them.
+ friend class type_safe_union<int, float, std::string>;
+
+};
+
+// ----------------------------------------------------------------------------------------
+
+int main()
+{
+ pipe_example pe;
+
+ // Make one of our type_safe_union objects
+ tsu_type msg;
+
+ // Treat our msg as a float and assign it 4.567
+ msg.get<float>() = 4.567f;
+ // Now put the message into the pipe
+ pe.message_pipe.enqueue(msg);
+
+ // Put a string into the pipe
+ msg.get<std::string>() = "string message";
+ pe.message_pipe.enqueue(msg);
+
+ // And now an int
+ msg.get<int>() = 7;
+ pe.message_pipe.enqueue(msg);
+
+ // And another string
+ msg.get<std::string>() = "yet another string message";
+ pe.message_pipe.enqueue(msg);
+
+
+ // the main function won't really terminate here. It will call the destructor for pe
+ // which will block until all the messages have been processed.
+}
+
+// ----------------------------------------------------------------------------------------
+