Hi, in a library I have a factory function that creates objects: ---- Main Library File ---- // Main io_service static boost::asio::io_service io_service; static boost::scoped_ptrboost::thread io_service_thread; static boost::asio::io_service::work* p_work; static BOOL thread_started; EXTERN_C EUROATLIB_API TETRAMotoHndl CALL GetTETRAMotoObj() { if (!thread_started) { try { // create the work object on the heap p_work = new boost::asio::io_service::work(io_service); // run the IO service as a separate thread io_service_thread.reset( new boost::thread( boost::bind(&boost::asio::io_service::run, &io_service) ) ); thread_started = !thread_started; } catch (boost::thread_resource_error e) { // Failed to create the new thread return 0; } } // create the new object TETRAMoto* pTETRAMoto = new TETRAMoto(io_service); // Assign a reference to io_service work object: // This reference is used to counting the objects created. // When the last TETRAMoto object is deleted the main work object // is destroyed and the io_service thread ends. pTETRAMoto->_io_work_ptr.reset(p_work); // return the object return pTETRAMoto; }; --------------------------------- These TETRAMoto objects creates another object, ATDispatcher, that use a SerialPort (which is a wrapper around asio::serial_port) to continuously read and write to RS232. When the SerialPort receive data, pass it to the ATDispatcher that raises a signal to the TETRAMoto object that parses the data and raise the event (always a signal) to the extern: asio::serial_port -> SerialPort -> ATDispatcher -> TetraMoto -|-> EXTERN Now I have to encapsulate this lib into an ActiveX DLL to be used by VB6 and I have to call CoInitizeEx in the thread that "raise" events.. My question is: where I have to call CoInitizeEx? Thanks in advance, Daniele.
When the SerialPort receive data, pass it to the ATDispatcher that raises a signal to the TETRAMoto object that parses the data and raise the event (always a signal) to the extern:
asio::serial_port -> SerialPort -> ATDispatcher -> TetraMoto -|-> EXTERN
Now I have to encapsulate this lib into an ActiveX DLL to be used by VB6 and I have to call CoInitizeEx in the thread that "raise" events..
My question is: where I have to call CoInitizeEx?
You can start the threads with your own thread-function (instead of io_service::run) that would call CoInitialize(), io_service::run(), CoUninitialize().
On Wed, Jun 3, 2009 at 12:45 PM, Igor R
When the SerialPort receive data, pass it to the ATDispatcher that raises a signal to the TETRAMoto object that parses the data and raise the event (always a signal) to the extern:
asio::serial_port -> SerialPort -> ATDispatcher -> TetraMoto -|-> EXTERN
Now I have to encapsulate this lib into an ActiveX DLL to be used by VB6 and I have to call CoInitizeEx in the thread that "raise" events..
My question is: where I have to call CoInitizeEx?
You can start the threads with your own thread-function (instead of io_service::run) that would call CoInitialize(), io_service::run(), CoUninitialize().
If you don't start the threads from the global scope (after the main has been entered) you may use the Schwarz-Counter (also known as Nifty-Counter) idiom. It is well described here: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter This is how Jerry Schwarz implemented the thread safe initialization of global iostream objects in STL: cout, cerr, clog etc. Regards, Ovanes
Ovanes Markarian ha scritto:
If you don't start the threads from the global scope (after the main has been entered) you may use the Schwarz-Counter (also known as Nifty-Counter) idiom.
It is well described here: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter
This is how Jerry Schwarz implemented the thread safe initialization of global iostream objects in STL: cout, cerr, clog etc.
Regards, Ovanes
Thanks Ovanes, It's interesting and I didn't know :-P Daniele.
Igor R ha scritto:
My question is: where I have to call CoInitizeEx?
You can start the threads with your own thread-function (instead of io_service::run) that would call CoInitialize(), io_service::run(), CoUninitialize().
Thanks a lot Igor! It was simple...and I didn't thought :-) Now seems to work: void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif io_service.run(); #if (WIN32) CoUninitialize(); #endif }; EXTERN_C EUROATLIB_API TETRAMotoHndl CALL GetTETRAMotoObj() { .... // run the IO service as a separate thread //io_service_thread.reset( // new boost::thread( // boost::bind(&boost::asio::io_service::run, &io_service) // ) //); io_service_thread.reset(new boost::thread(io_worker_thread)); ... }; Thanks! Daniele.
On Wed, Jun 3, 2009 at 3:21 PM, Daniele Barzotti < daniele.barzotti@eurocomtel.com> wrote:
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
It is better to use at least RAII here. This approach is not exception safe and if io_service.run() throws an exception CoUnintialize() will not be called.
On Wed, Jun 3, 2009 at 8:35 AM, Ovanes Markarian
On Wed, Jun 3, 2009 at 3:21 PM, Daniele Barzotti < daniele.barzotti@eurocomtel.com> wrote:
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
It is better to use at least RAII here. This approach is not exception safe and if io_service.run() throws an exception CoUnintialize() will not be called.
For per-thread COM Initialization in the presence of boost I almost always
do the following:
//Put in a widely visible header file somewhere
struct com_init;
extern boost::thread_specific_ptr
Ovanes Markarian ha scritto:
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
It is better to use at least RAII here. This approach is not exception safe and if io_service.run() throws an exception CoUnintialize() will not be called.
You're right! But how can I adapt this code to use RAII? Maybe is more simple to add a try-catch statement? Daniele.
On Wed, Jun 3, 2009 at 3:57 PM, Daniele Barzotti < daniele.barzotti@eurocomtel.com> wrote:
Ovanes Markarian ha scritto:
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
It is better to use at least RAII here. This approach is not exception safe and if io_service.run() throws an exception CoUnintialize() will not be called.
You're right! But how can I adapt this code to use RAII? Maybe is more simple to add a try-catch statement?
Daniele.
Zachary's example does it. You can also use the shared_ptr do it locally in the function by passing the deleter function. Or you just write your io_worker_thread() so: void io_worker_thread() { # if(WIN32) struct com_init { com_init() { CoInitializeEx(...); } ~com_init() { CoUninitialize(); } } initializer_object; # endif io_service.run(); } That's it. ;) Regards, Ovanes
On Wed, Jun 3, 2009 at 8:57 AM, Daniele Barzotti < daniele.barzotti@eurocomtel.com> wrote:
Ovanes Markarian ha scritto:
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
It is better to use at least RAII here. This approach is not exception safe and if io_service.run() throws an exception CoUnintialize() will not be called.
You're right! But how can I adapt this code to use RAII? Maybe is more simple to add a try-catch statement?
See the example I gave above using thread_specific_ptr. thread_specific_ptr frees its objects when the thread exits and the example above works regardless of whether or not you are always only using COM from threads you've created manually. If you always create the threads manually and have control over their thread function, just declare a copy of my com_init class on the stack in the first line of your thread function.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 03 June 2009, Zachary Turner wrote:
You're right! But how can I adapt this code to use RAII? Maybe is more simple to add a try-catch statement?
See the example I gave above using thread_specific_ptr. thread_specific_ptr frees its objects when the thread exits and the example above works regardless of whether or not you are always only using COM from threads you've created manually.
Why are so many people's quoting in the plain-text version of their emails broken? Is this a gmail problem? -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEUEARECAAYFAkomiVIACgkQ5vihyNWuA4XzlQCXdxJSYcuN3s5kTOmE/h35wdMo 1wCgrQgcy1sSzPFuREDofFwzWxqGQPU= =2zD3 -----END PGP SIGNATURE-----
On Wed, Jun 3, 2009 at 9:31 AM, Frank Mori Hess
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Wednesday 03 June 2009, Zachary Turner wrote:
You're right! But how can I adapt this code to use RAII? Maybe is more simple to add a try-catch statement?
See the example I gave above using thread_specific_ptr. thread_specific_ptr frees its objects when the thread exits and the example above works regardless of whether or not you are always only using COM from threads you've created manually.
Why are so many people's quoting in the plain-text version of their emails broken? Is this a gmail problem?
I never even realized it was a problem until you mentioned that :P It always displays perfectly under gmail. Is this better? Guess it's due to the way they handle quotes if rich formatting is turned on (which is the default).
void io_worker_thread(void) { #if (WIN32) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif
io_service.run();
#if (WIN32) CoUninitialize(); #endif };
EXTERN_C EUROATLIB_API TETRAMotoHndl CALL GetTETRAMotoObj() { .... // run the IO service as a separate thread
//io_service_thread.reset( // new boost::thread( // boost::bind(&boost::asio::io_service::run, &io_service) // ) //);
io_service_thread.reset(new boost::thread(io_worker_thread));
... };
You forgot you to pass the io_service to the io_worker_thread.
Igor R ha scritto:
EXTERN_C EUROATLIB_API TETRAMotoHndl CALL GetTETRAMotoObj() { .... // run the IO service as a separate thread
//io_service_thread.reset( // new boost::thread( // boost::bind(&boost::asio::io_service::run, &io_service) // ) //);
io_service_thread.reset(new boost::thread(io_worker_thread));
... };
You forgot you to pass the io_service to the io_worker_thread.
The io_service object is declared as static in the module: // Main io_service static boost::asio::io_service io_service; Daniele.
participants (5)
-
Daniele Barzotti
-
Frank Mori Hess
-
Igor R
-
Ovanes Markarian
-
Zachary Turner