F
Hi!
Nur so als Anregung: Ich verwende gerne eine Basisklasse für sehr allgemeine Arbeits-Threads, die nicht viel anderes machen als std::function -Objekte in einem queue der Reihe nach auszuführen. So kann man dem Thread bequem beliebige Aufgaben geben, oder bei Bedarf die Basisklasse auch für spezialisierte Aufgaben erweitern. Ich weiss zwar nicht, was für Briefe sich deine Threads so schreiben, aber auf so einem function-Arbeitstread kann man durchaus ein Message-System aufsetzen. Das, was du mit deiner "Multipurpose"-Nachricht erreichen möchtes (so wie ich es verstanden habe) lasse ich dabei einfach von std::bind erledigen. Als Prototyp sähe das Ganze dann grob etwa so aus:
#include <functional>
#include <string>
#include <memory>
#include <mutex>
#include <deque>
struct Object
{
void print()
{
std::cout << "Hallo vom Objekt!" << std::endl;
}
};
class WorkerThread
{
public:
typedef std::function<void()> TaskFunction;
void enqueue(TaskFunction taskFunction)
{
std::lock_guard<std::mutex> lock(queueMutex);
taskQueue.emplace_back(std::move(taskFunction));
}
void threadFunction()
{
{
std::lock_guard<std::mutex> lock(queueMutex);
while (!taskQueue.empty())
{
taskQueue.front()();
taskQueue.pop_front();
}
}
// Warten, bis queue nicht mehr leer (condition variable o.ä.)
}
private:
std::mutex queueMutex;
std::deque<TaskFunction> taskQueue;
};
class MessageThread : public WorkerThread
{
public:
class Message
{
friend class MessageThread;
protected:
typedef std::function<void(MessageThread* thread)> MessageFunction;
Message(MessageFunction messageFunction)
: messageFunction(std::move(messageFunction))
{
}
private:
MessageFunction messageFunction;
};
class Message1 : public Message
{
public:
Message1(int arg1, std::string arg2, const std::shared_ptr<Object>& arg3)
: Message(std::bind(&MessageThread::message1Function, std::placeholders::_1, arg1, arg2, arg3))
{
}
};
void enqueue(const Message& message)
{
WorkerThread::enqueue(std::bind(message.messageFunction, this));
}
private:
void message1Function(int arg1, std::string arg2, const std::shared_ptr<Object>& object)
{
std::cout << "Nachricht Typ 1 #" << arg1 << ": string = " << arg2 << std::endl;
object->print();
}
};
int main()
{
MessageThread thread;
auto object = std::make_shared<Object>();
std::cout << "ENQUEUE" << std::endl;
thread.enqueue(MessageThread::Message1(1, "Nachricht 1", object));
thread.enqueue(MessageThread::Message1(2, "Nachricht 2", object));
thread.enqueue(MessageThread::Message1(3, "Nachricht 3", object));
std::cout << "PROCESS" << std::endl;
thread.threadFunction();
}
Der Code ist natürlich noch zu verfeinern, aber ich denke die Idee kommt rüber.
Vielleicht ist das ja eine etwas bequemer zu implementierende Alternative.
Gruss,
Finnegan