diff options
Diffstat (limited to 'src/ml/dlib/examples/pipe_ex_2.cpp')
-rw-r--r-- | src/ml/dlib/examples/pipe_ex_2.cpp | 160 |
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. +} + +// ---------------------------------------------------------------------------------------- + |