Designing Thread Class - c++

I have a design question. Is it better to define separate classes for SENDING and RECEIVING. Or, is it better to define a single Thread class? I like the idea of a single Thread class because it is easier to share a queue which can be locked by mutex.
Design Option #1 (Separate):
mySendThread = new SendThread(); // Have thread properties and separate members
myRcvThread = new RcvThread(); // Have thread properties and separate members
Design Option #2 (Master):
Master thread -
Execute()
{
if (threadType == RCV_THREAD)
{
globalVar = new MasterThread(serialPortHandle);
}
while (!Terminated)
{
if (threadType == RCV_THREAD)
{
if(globalVar)
{
// do work
}
}
if (threadType == SND_THREAD)
{
tCountSnd = GetTickCount() / SND_THREAD_DELAY;
if (tCountSnd != tCountSnd2) {
tCountSnd2 = tCountSnd;
if (globalVar) {
// do sending work
}
}
}
}
}

I think it's better to completely decouple the purpose or execution of a thread from the actual thread abstraction that you'll be using.
Make your thread class just a thin wrapper to allow you to start, stop, and join a thread. Have it take a functor object (or function pointer) in the constructor for the actual execution.
Or better yet, use one of the many available thread abstractions already out there instead of writing your own (boost::thread for one, but I bet whatever framework you're using already has a thread class).

I've designed a thread for communicating on the serial port (in Python, not C++, but it doesn't matter much) as follows:
There's a single thread and two queues - one for sent and one for received messages. The thread always listens (asynchronously) on both the serial port (for received data) and the sending queue (to send stuff the application asks to send).
If data arrived on the serial port, it's placed in the receive queue for the application's use
If the application placed data into the send queue, the thread sends it down the serial port
This design makes more sense to me because the single resource (the serial port) is held by a single thread, and not shared by two. Breaking it to several classes sounds like an overkill to me, since reading/writing from queues and reading/writing from the serial port is a trivial operation (naturally the serial port is wrapped in a convenient class - by the way I really recommend this class by Ramon De Klein)
Oh, and it works very well.

Regarding the queue to be shared .. wrap it in a separate class and implement the mutex handling there. Every thread class holds a reference to the queue wrapper and doesn't need to deal around with mutexes at all.

2nd choice is clearly a bad one.
It is better to have 2 different classes , maybe you can have a base class which has common implementation. This is just an initial assessment please provide more information about your problem only then a good analysis of problem can be done

Related

QT c++ QFutures with signals without QConcurrent, like promises/observables?

I'm fuguring out how to use Futures with non-blocking event driven code (in a separate thread or not, both) but how can i end the future from a slot (~resolve the promise based on an signal) ?
QByteArray RfidCardReader::startTask(QByteArray send)
{
if(this->busy==false) {
this->sendFrame(send);
QObject::connect(this, &RfidCardReader::frameReady,
[=]() {/*this must be the startTask return*/ return this->int_read_buffer;});
} else {
throw 0;//Handle a queue instead
}
}
QFuture<QByteArray> RfidCardReader::send(QByteArray passed_send)
{
return QtConcurrent::run(QThreadPool::globalInstance(), this->startTask, passed_send);
}
basically what I want to do using only an instance is wrap a serial device (whic is sync by nature) in a queue of Futures but with only non blocking code using signals like &QIODevice::bytesWritten &QIODevice::readyRead etc... if there are better approches to the problem let me know, i would be glad to know the right way to write readable async code in Qt without blocking in separate threads
A serial device is asynchronous by nature, and using the serial port concurrently from multiple threads is undefined behavior. You can certainly resolve futures from any thread, but there's nothing in Qt that will give you a future on the same thread. Recall that a QFuture is not a class that you can sensibly instantiate. The default-constructed class is useless.
To get an idea of how to handle asynchronous serial I/O, see for example this answer.
Then you can use the undocumented <QFutureInterface> header, and create your own implementation that can wrap higher-level aspects of your protocol, i.e. commands/requests. You could then group such futures, and use a single watcher to determine when they are done.
Your approach is quite interesting in fact, and I might develop a complete example.

Multithreading and Global instances of classes?

I am using mutlithreading 'first time' for a network application, my question is two related part ,
If i represent for example bunch of messages in udp with a classes (each message a class), would it be a good practice to make instances of such classes global in order to send them at different threads, or the better approach is to use a struct having a class instance and all the socket information as a reference inside that struct (then use Pthread_create )
I reckon that in the first option , a great deal of care must be taken in order to avoid simultaneous access to data (use the pthread_mutex )
please suggest how would you approach this problem.
I really would appreciate thehelp
Thank you very much
If I understand your question correctly, you plan to have a listener thread that receveives messages and dispatches them to several threads that process these message concurently.
Here a possible approach would be to use a shared queue:
The listner push() the messages it receives on the queue :
The worker threads, if the queue is not empty(), take the next element to process (front()``andpop()`)
Of course the queue shall be locked when reading or writing elements with a mutex, unless you use a lokc-free queue implementation.
Only the queue needs to be shared. You can do this with a global definition. But on the other side, it's good practice to avoid global variables/objects whenver you can. So you'd better instantiate the queue dynamically when you create and launch your threads and pass the reference to the queueue to each of them.
With C++11 standard threads it would look somewhat like:
...
std::queue<my_message_class> work_to_do; // create queue
std::thread t1(listener, std::ref(work_to_do)); // launch listener
int n = max(2, std::thread::hardware_concurrency()-1); // maximize concurency for the hardware
std::vector<std::thread> workers;
for (int i = 0; i < n; i++) {
v.push_back(std::thread{ worker_function, std::ref(work_to_do) });
}
... // do something else and wait until it finishes
t1.join(); // wait until listner finishes
for (auto& x : workers) { // wait until all the worker threads finish.
x.join();
}
...
where void listener(std::queue<my_message_class>& q) and void worker(std::queue<my_message_class>& q) would be the functions to execute.
Of course, you could do similar things with pthreads. But the standards ones have the advantage of being platform independent.

c++ sharing single class object between multiple processes

I have a relatively complex class in c++. It works perfectly when used within one process. However, now I want multiple processes to be able to share one object instance of this class. One process (Master) will access read and write functions of the object, while the other 2 processes (Slave) will only use the read functions. I want to modify the class as little as possible. So far I have considered singletons and shared memory, but neither seems ideal or straightforward. This is a research application that will only ever be used by me on Linux. What is the simplest possible solution?
Thanks so much!
Edit: To be absolutely clear, the asker is interested in sharing an object across multiple processes, not threads.
Inter-process communication is never simple. You may want to use a library for IPC/RPC and expose only the function the slaves use to read data, not the entire class.
I can't give you any good recommendations because I have never found a library that made it simple and I don't have much experience with it.
One idea might be to use socket or a socket library to share the data amongst the processes. A library which seems to be very handy for that might be ØMQ. You can also try to use Boost::Asio which is a bit more complex.
You can find a small example for ØMQ here.
I think the simplest coding solution would be a singleton with a global(or class instance) mutex, though the singleton part of that is optional. I personally think singletons to be an overused idiom. Up to you whether you think that is good design in this case or not. Really, adding the global mutex is all you need.
For the interprocess portion, I recommend boost.
http://www.boost.org/doc/libs/1_36_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_interprocess_semaphores
One option is to have both the master and slave processes create instances of the same object. Because the master process will be the only one to modify this 'shared' object, it must only alert the slaves processes to any changes it makes to the 'shared' object. To do this, you could setup a messaging system which the master process will use to communicate changes to the shared object with the slave processes. The drawback here is that the slave processes may reference the shared object when it is out of sync with the master, but this is a common problem in replication. Also, you could use an RPC overlay to further make the master/slave applications easier to develop/maintain.
I'll try and provide a very high level example of this design below. Forgive me for utilizing real code and psuedo code side-by-side; I didn't want to fully code this, but also didn't want it to just be made up of comments :)
Here's our shared object that gets defined in both master/slave code
struct sharedobj {
int var1;
};
Here's an example of the master process updating the shared object and propagating changes
int counter = 0;
sharedobj mysharedobj;
while(true){
//update the local version first
mysharedobj.var1 = counter++;
//then call some function to push these changes to the slaves
updateSharedObj(mysharedobj);
}
Here's the function that propagates the master's changes to the slaves;
updatedSharedObj(sharedobj obj){
//set up some sort of message that encompasses these changes
string msg = "var1:" + the string value of obj.var1;
//go through the set of slave processes
//if we've just done basic messaging, maybe we have a socket open for each process
while(socketit != socketlist.end()){
//send message to slave
send(*socketit, msg.c_str(),msg.length(),0);
}
}
And here's the slave code that receives these changes and updates its 'shared' object; most likely running in another thread so slave can run without having to stop and check for object updates.
while(true){
//wait on the socket for updates
read(mysock,msgbuf,msgbufsize,0);
//parse the msgbuf
int newv1 = the int value of var1 from the msg;
//if we're in another thread we need to synchronize access to the object between
//update thread and slave
pthread_mutex_lock(&objlock);
//update the value of var1
sharedobj.var1 = newv1;
//and release the lock
pthread_mutex_unlock(&objlock);
}
See "shared memory" in Boost Interprocess: http://www.boost.org/doc/libs/1_63_0/doc/html/interprocess/sharedmemorybetweenprocesses.html

Design a transmitter class in C++: buffer data from server & send to client

I'm writing a class "Tmt" that acts between a server and clients through sockets. My Tmt class will receive data from server, build up a queue internally and perform some operation on the data in the queue before they are available to the client.
I have already setup the socket connection and I can call
receiverData(); // to get data from server
The client will use my class Tmt as follows:
Tmt mytmt=new Tmt();
mymt.getProcessedData(); //to get one frame.
My question is how to let the Tmt class keep receiving data from server in the background once it is created and add them to the queue. I have some experience in multi-thread in C, but I'm not sure how this "working in the background" concept will be implemented in a class in C++. Please advice, thanks!
One option would be to associate a thread with each instance of the class (perhaps by creating a thread in the constructor). This thread continuously reads data from the network and adds the data to the queue as it becomes available. If the thread is marked private (i.e. class clients aren't aware of its existence), then it will essentially be running "in the background" with no explicit intervention. It would be up to the Tmt object to manage its state.
As for actual thread implementations in C++, you can just use Good ol' Pthreads in C++ just fine. However, a much better approach would probably be to use the Boost threading library, which encapsulates all the thread state into its own class. They also offer a whole bunch of synchronization primitives that are just like the pthread versions, but substantially easier to use.
Hope this helps!
By the way - I'd recommend just naming the class Transmit. No reason to be overly terse. ;-)
IMHO, multithreading is not the best solution for this kind of classes.
Introducing background threads can cause many problems, you must devise guards against multiple unnecessary thread creation at the least. Also threads need apparent initialize and cleanup. For instance, usual thread cleanup include thread join operation (wait for thread to stop) that could cause deadlocks, resource leaks, irresponsible UIs, etc.
Single thread asynchronous socket communication could be more appropriate to this scenario.
Let me draw sample code about this:
class Tmt {
...
public:
...
bool doProcessing()
{
receiverData();
// process data
// return true if data available
}
T getProcessedData()
{
// return processed data
}
}
Tmt class users must run loop doing doProcessing, getProcessedData call.
Tmt myTmt;
...
while (needMoreData)
{
if (myTmt.doProcessing())
{
myTmt.getProcessedData();
...
}
}
If Tmt users want background processing they can easily create another thread and doing Tmt job in there. This time, thread management works are covered by Tmt users.
If Tmt users prefer single thread approach they can do it without any problem.
Also noted that famous curl library uses this kind of design.

How to handle same socket in different threads?

I am trying to handle socket in different threads creating runtime failure. See following code.
void MySocket::Lock()
{
m_LockCount++;
if( m_LockCount )
{
CSocket::Create( 8080 );
}
}
void MySocket::Unlock()
{
m_LockCount--;
if( !m_LockCount )
{
CSocket::Close();
}
}
I am calling Lock() from one thread and Unlock() from other. When it executes CSocket::Close() it gives an exception.
I googled for this bug and got some reasons.
This happens because; a CSocket object should be used only in the context of a single thread because the SOCKET handle encapsulated by a CAsyncSocket object is stored in a per-thread handle map. They are also suggesting a solution by sharing SOCKET handles between threads (http://support.microsoft.com/kb/175668). But this is not possible in my case since I am excepting some notification callback which will not work with above solution. Can anybody suggest a mechanism to share CSocket among threads without effecting notification callbacks?
You coould just use the socket directly and stop using the, obviously, flawed MFC implementation ...
If, as you say, "a CSocket object should be used only in the context of a single thread," then there is no "mechanism to share CSocket among threads".
In other words, one of the threads needs to own the CSocket, and the others can't mess with it.
In such cases, the solution is to use an inter-thread messaging system. That way, one of the other threads can send a message to the owner saying, "Hey, buddy, close your socket!"
The details of how you would do that messaging depend entirely on the context of your program.
I would advise you to use some higher-level (and less buggy) socket API like Boost.Asio. Note that it does not make sockets thread-safe anyway (see there). You have to use some lock/unlock facility.
I am not sure i understand your question about sharing sockets among threads without using notification callbacks. Between threads T1 and T2, supposing T1 manages a socket, there are only two ways for T2 to become aware of a socket event. Either some notification launched by T1 or a question asked by T2 to T1, either on a regular basis or in a blocking call.