Boost - Threading several processes over several sessions - c++

I am currently running into several problems while threading a couple different processes with boost. I am fairly new to threading so bear with me. Hopefully the formatting is good enough as well.
I have two threads defined.
boost::thread m_thread1;
boost::thread m_thread2;
Associated with these threads are three futures and two packaged_tasks
boost::packaged_task<bool> ptaskBool;
boost::packaged_task<double> ptaskDouble;
boost::unique_future<bool> futureBool;
boost::unique_future<double> futureDouble1;
boost::unique_future<double> futureDouble2;
Both of these threads are defined inside a while loop
while(running)
{
//some code
if(!thread1running)
{
ptaskBool = boost::packaged_task<bool>(boost::bind(/*some objects function*/));
futureBool = ptaskBool.get_future();
m_thread1 = boost::thread(boost::move(ptaskBool));
thread1running = true;
}
if(!thread2running && initial)
{
ptaskDouble = boost::packaged_task<bool>(boost::bind(/*some objects function*/));
futureDouble = ptaskDouble.get_future();
m_thread2 = boost::thread(boost::move(ptaskDouble));
thread2running = true;
}
else if(!thread2running)
{
ptaskDouble = boost::packaged_task<bool>(boost::bind(/*some different function*/));
futureDouble2 = ptaskDouble.get_future();
m_thread2 = boost::thread(boost::move(ptaskDouble));
initial = true;
thread2running = true;
}
This is a simplification of what I have but it is very similar. The next code I have is for the futures.
if(futureBool.is_ready())
{
m_bool = futureBool.get();
thread1running = false;
}
if(futureDouble.is_ready())
{
m_double = futureDouble.get();
std::cout << "Result: " << m_double << std::endl;
thread2running = false;
//have tried several things like a join here to no avail
}
if(futureDouble2.is_ready())
{
m_double = futureDouble2.get();
std::cout << "Result: " << m_double << std::endl;
thread2running = false;
}
}//end while
What I meant by sessions in the title is that there is some session handling in the background to do with telling the threads when and when not to be created.
There is other code that does some processing and flag checking but it is not relevant to my question. I am clearly misunderstanding something that is going on. The first time each thread is run, they complete their tasks. The second time the program just crashes.
I have had luck with making each thread variable a pointer and defining a new thread every time instead of redefining each thread. This worked but I was unable to delete each thread after completion. What am I not understanding here? What is the thread actually doing after the function returns a result?

auto_ptr is a good way to ensure your threads will be deleted at the end. Also is unique_ptr from C++11.
According to: http://www.cplusplus.com
Note: This class template (auto_ptr) is deprecated as of C++11. unique_ptr is a new facility with a similar functionality, but with improved security (no fake copy assignments), added features (deleters) and support for arrays. See unique_ptr for additional information.
See Using auto_ptr Effectively for examples using auto_ptr.

Related

Converting an unruly dependency injection model with a service locator

I've been using DI for a game engine project for a while and I just hit a wall; given the below order of creation: The job system does not depend on anything and everything depends on the file logger. It makes sense to create the job system, then the file logger, then pass the created references for each dependency down to its dependents' constructors.
App::App(const std::string& cmdString)
: EngineSubsystem()
, _theJobSystem{std::make_unique<JobSystem>(-1, static_cast<std::size_t>(JobType::Max), new std::condition_variable)}
, _theFileLogger{std::make_unique<FileLogger>(*_theJobSystem.get(), "game")}
, _theConfig{std::make_unique<Config>(KeyValueParser{cmdString})}
, _theRenderer{std::make_unique<Renderer>(*_theJobSystem.get(), *_theFileLogger.get(), *_theConfig.get())}
, _theInputSystem{std::make_unique<InputSystem>(*_theFileLogger.get(), *_theRenderer.get())}
, _theUI{std::make_unique<UISystem>(*_theFileLogger.get(), *_theRenderer.get(), *_theInputSystem.get())}
, _theConsole{std::make_unique<Console>(*_theFileLogger.get(), *_theRenderer.get())}
, _theAudioSystem{std::make_unique<AudioSystem>(*_theFileLogger.get()) }
, _theGame{std::make_unique<Game>()}
{
SetupEngineSystemPointers();
SetupEngineSystemChainOfResponsibility();
LogSystemDescription();
}
void App::SetupEngineSystemPointers() {
g_theJobSystem = _theJobSystem.get();
g_theFileLogger = _theFileLogger.get();
g_theConfig = _theConfig.get();
g_theRenderer = _theRenderer.get();
g_theUISystem = _theUI.get();
g_theConsole = _theConsole.get();
g_theInputSystem = _theInputSystem.get();
g_theAudioSystem = _theAudioSystem.get();
g_theGame = _theGame.get();
g_theApp = this;
}
void App::SetupEngineSystemChainOfResponsibility() {
g_theConsole->SetNextHandler(g_theUISystem);
g_theUISystem->SetNextHandler(g_theInputSystem);
g_theInputSystem->SetNextHandler(g_theApp);
g_theApp->SetNextHandler(nullptr);
g_theSubsystemHead = g_theConsole;
}
As you can see, passing the different subsystems around to the other subsystem constructors is starting to get messy. In particular when dealing with jobs, logging, console commands, UI, configuration, and audio (and physics, not pictured).
(Side note: These are going to eventually be replaced with interfaces created via factories for cross-compatibility, i.e. the Renderer is strictly a DirectX/Windows-only renderer but I want to eventually support OpenGL/Linux; that's why everything is passed around as references and created as pointers instead of a concrete types)
I've run in to situations where pretty much all the subsystems are in some way dependent on every other subsystem.
But, due to construction-order problems, Dependency Injection does not work because one or more of the required-to-exist subsystems hasn't been constructed yet. Same problem with two-phase construction: the subsystem may not have been initialized by the time it's needed further downstream.
I looked in to the service locator pattern and this question deems it a bad idea, but the game industry likes using bad ideas (like global variables to every subsystem for game-specific code to use) if they work.
Would converting to a service locator fix this problem?
What other implementations do you know of that could also fix the issue?
I ultimately went with the ServiceLocator pattern, deriving every subsystem that was a dependency as a Service:
App::App(const std::string& cmdString)
: EngineSubsystem()
, _theConfig{std::make_unique<Config>(KeyValueParser{cmdString})}
{
SetupEngineSystemPointers();
SetupEngineSystemChainOfResponsibility();
LogSystemDescription();
}
void App::SetupEngineSystemPointers() {
ServiceLocator::provide(*static_cast<IConfigService*>(_theConfig.get()));
_theJobSystem = std::make_unique<JobSystem>(-1, static_cast<std::size_t>(JobType::Max), new std::condition_variable);
ServiceLocator::provide(*static_cast<IJobSystemService*>(_theJobSystem.get()));
_theFileLogger = std::make_unique<FileLogger>("game");
ServiceLocator::provide(*static_cast<IFileLoggerService*>(_theFileLogger.get()));
_theRenderer = std::make_unique<Renderer>();
ServiceLocator::provide(*static_cast<IRendererService*>(_theRenderer.get()));
_theInputSystem = std::make_unique<InputSystem>();
ServiceLocator::provide(*static_cast<IInputService*>(_theInputSystem.get()));
_theAudioSystem = std::make_unique<AudioSystem>();
ServiceLocator::provide(*static_cast<IAudioService*>(_theAudioSystem.get()));
_theUI = std::make_unique<UISystem>();
_theConsole = std::make_unique<Console>();
_theGame = std::make_unique<Game>();
g_theJobSystem = _theJobSystem.get();
g_theFileLogger = _theFileLogger.get();
g_theConfig = _theConfig.get();
g_theRenderer = _theRenderer.get();
g_theUISystem = _theUI.get();
g_theConsole = _theConsole.get();
g_theInputSystem = _theInputSystem.get();
g_theAudioSystem = _theAudioSystem.get();
g_theGame = _theGame.get();
g_theApp = this;
}
void App::SetupEngineSystemChainOfResponsibility() {
g_theConsole->SetNextHandler(g_theUISystem);
g_theUISystem->SetNextHandler(g_theInputSystem);
g_theInputSystem->SetNextHandler(g_theRenderer);
g_theRenderer->SetNextHandler(g_theApp);
g_theApp->SetNextHandler(nullptr);
g_theSubsystemHead = g_theConsole;
}

Boost::Thread: Removing a thread from a dynamic group?

Consider this context:
Having a group of threads doing some work (that work is in a infinite loop, embedded project) where the number of threads (and some parameters) depends from a Database result.
What I need is to remove or create threads from that group when there´s a change in the database.
Here is the code:
for (result::const_iterator pin = pinesBBB.begin(); pin != pinesBBB.end(); ++pin)
{
string pinStr = pin["pin"].as<string>();
boost::thread hiloNuevo(bind(WorkPin, pinStr));
Worker.add_thread(&hiloNuevo);
}
Where result is pqxx::result from pqxx library.
This piece of code iterates a table from an SQL query result and creates a thread for every record found.
After that, there´s this code that checks the same table every a couple of minutes:
`
void ThreadWorker(boost::thread_group *worker, string *pinesLocales)
{
int threadsVivosInt = worker->size();
string *pinesDB;
int contador;
for (;;)
{
contador = 0;
sleep(60);
try
{
result pinesBBB = TraerPines();
for (result::const_iterator pin = pinesBBB.begin(); pin != pinesBBB.end(); ++pin)
{
pinesDB[contador] = pin["pin"].as<string>();
contador++;
}
thread hiloMuerto
}
catch (...)
{
sleep(360);
}
}
}
`
What I want to do is access this thread_group worker and remove one of those threads.
I´ve tryed using an Int index like worker[0] and with thread´s ID boost::thread::id
I can remove a thread using a native_handle and then using an plattform specific like pthread_cancel but I can´t get the thread from the thread group.
Any ideas? Thanks!
boost::thread_group::remove_thread() removes the specified thread from a given thread_group. Once you've done this, you're now responsible for managing the thread.

MySQL Asynchronous?

Im basically facing a blocking problem.
I have my server coded based on C++ Boost.ASIO using 8 threads since the server has 8 logical cores.
My problem is a thread may face 0.2~1.5 seconds of blocking on a MySQL query and I honestly don't know how to go around that since MySQL C++ Connector does not support asynchronous queries, and I don't know how to design the server "correctly" to use multiple threads for doing the queries.
This is where I'm asking for opinions of what to do in this case.
Create 100 threads for async' query sql?
Could I have an opinion from experts about this?
Okay, the proper solution to this would be to extend Asio and write a mysql_service implementation to integrate this. I was almost going to find out how this is done right away, but I wanted to get started using an "emulation".
The idea is to have
your business processes using an io_service (as you are already doing)
a database "facade" interface that dispatches async queries into a different queue (io_service) and posts the completion handler back onto the business_process io_service
A subtle tweak needed here you need to keep the io_service on the business process side from shutting down as soon as it's job queue is empty, since it might still be awaiting a response from the database layer.
So, modeling this into a quick demo:
namespace database
{
// data types
struct sql_statement { std::string dml; };
struct sql_response { std::string echo_dml; }; // TODO cover response codes, resultset data etc.
I hope you will forgive my gross simplifications :/
struct service
{
service(unsigned max_concurrent_requests = 10)
: work(io_service::work(service_)),
latency(mt19937(), uniform_int<int>(200, 1500)) // random 0.2 ~ 1.5s
{
for (unsigned i = 0; i < max_concurrent_requests; ++i)
svc_threads.create_thread(boost::bind(&io_service::run, &service_));
}
friend struct connection;
private:
void async_query(io_service& external, sql_statement query, boost::function<void(sql_response response)> completion_handler)
{
service_.post(bind(&service::do_async_query, this, ref(external), std::move(query), completion_handler));
}
void do_async_query(io_service& external, sql_statement q, boost::function<void(sql_response response)> completion_handler)
{
this_thread::sleep_for(chrono::milliseconds(latency())); // simulate the latency of a db-roundtrip
external.post(bind(completion_handler, sql_response { q.dml }));
}
io_service service_;
thread_group svc_threads; // note the order of declaration
optional<io_service::work> work;
// for random delay
random::variate_generator<mt19937, uniform_int<int> > latency;
};
The service is what coordinates a maximum number of concurrent requests (on the "database io_service" side) and ping/pongs the completion back onto another io_service (the async_query/do_async_query combo). This stub implementation emulates latencies of 0.2~1.5s in the obvious way :)
Now comes the client "facade"
struct connection
{
connection(int connection_id, io_service& external, service& svc)
: connection_id(connection_id),
external_(external),
db_service_(svc)
{ }
void async_query(sql_statement query, boost::function<void(sql_response response)> completion_handler)
{
db_service_.async_query(external_, std::move(query), completion_handler);
}
private:
int connection_id;
io_service& external_;
service& db_service_;
};
connection is really only a convenience so we don't have to explicitly deal with various queues on the calling site.
Now, let's implement a demo business process in good old Asio style:
namespace domain
{
struct business_process : id_generator
{
business_process(io_service& app_service, database::service& db_service_)
: id(generate_id()), phase(0),
in_progress(io_service::work(app_service)),
db(id, app_service, db_service_)
{
app_service.post([=] { start_select(); });
}
private:
int id, phase;
optional<io_service::work> in_progress;
database::connection db;
void start_select() {
db.async_query({ "select * from tasks where completed = false" }, [=] (database::sql_response r) { handle_db_response(r); });
}
void handle_db_response(database::sql_response r) {
if (phase++ < 4)
{
if ((id + phase) % 3 == 0) // vary the behaviour slightly
{
db.async_query({ "insert into tasks (text, completed) values ('hello', false)" }, [=] (database::sql_response r) { handle_db_response(r); });
} else
{
db.async_query({ "update * tasks set text = 'update' where id = 123" }, [=] (database::sql_response r) { handle_db_response(r); });
}
} else
{
in_progress.reset();
lock_guard<mutex> lk(console_mx);
std::cout << "business_process " << id << " has completed its work\n";
}
}
};
}
This business process starts by posting itself on the app service. It then does a number of db queries in succession, and eventually exits (by doing in_progress.reset() the app service is made aware of this).
A demonstration main, starting 10 business processes on a single thread:
int main()
{
io_service app;
database::service db;
ptr_vector<domain::business_process> bps;
for (int i = 0; i < 10; ++i)
{
bps.push_back(new domain::business_process(app, db));
}
app.run();
}
In my sample, business_processes don't do any CPU intensive work, so there's no use in scheduling them across CPU's, but if you wanted you could easily achieve this, by replacing the app.run() line with:
thread_group g;
for (unsigned i = 0; i < thread::hardware_concurrency(); ++i)
g.create_thread(boost::bind(&io_service::run, &app));
g.join_all();
See the demo running Live On Coliru
I'm not a MySQL guru, but the following is generic multithreading advice.
Having NumberOfThreads == NumberOfCores is appropriate when none of the threads ever block and you are just splitting the load over all CPUs.
A common pattern is to have multiple threads per CPU, so one is executing while another is waiting on something.
In your case, I'd be inclined to set NumberOfThreads = n * NumberOfCores where 'n' is read from a config file, a registry entry or some other user-settable value. You can test the system with different values of 'n' to fund the optimum. I'd suggest somewhere around 3 for a first guess.

MongoDB C++ driver handling replica set connection failures

So the mongo c++ documentation says
On a failover situation, expect at least one operation to return an
error (throw an exception) before the failover is complete. Operations
are not retried
Kind of annoying, but that leaves it up to me to handle a failed operation. Ideally I would just like the application to sleep for a few seconds (app is single threaded). And retry with the hopes that a new primary mongod is established. In the case of a second failure, well I take it the connection is truly messed up and I just want to thrown an exception.
Within my MongodbManager class this means all operations have this kind of double try/catch block set up. I was wondering if there is a more elegant solution?
Example method:
template <typename T>
std::string
MongoManager::insert(std::string ns, T object)
{
mongo::BSONObj = convertToBson(object);
std::string result;
try {
connection_->insert(ns, oo); //connection_ = shared_ptr<DBClientReplicaSet>
result = connection_->getLastError();
lastOpSucceeded_ = true;
}
catch (mongo::SocketException& ex)
{
lastOpSucceeded_ = false;
boost::this_thread::sleep( boost::posix_time::seconds(5) );
}
// try again?
if (!lastOpSucceeded_) {
try {
connection_->insert(ns, oo);
result = connection_->getLastError();
lastOpSucceeded_ = true;
}
catch (mongo::SocketException& ex)
{
//do some clean up, throw exception
}
}
return result;
}
That's indeed sort of how you need to handle it. Perhaps instead of having two try/catch blocks I would use the following strategy:
keep a count of how many times you have tried
create a while loop with as terminator (count < 5 && lastOpSucceeded)
and then sleep with pow(2,count) to sleep more in every iteration.
And then when all else fails, bail out.

AppFabric Cache concurrency issue?

While stress testing prototype of our brand new primary system, I run into concurrent issue with AppFabric Cache. When concurrently calling many DataCache.Get() and Put() with same cacheKey, where I attempt to store relatively large objet, I recieve "ErrorCode:SubStatus:There is a temporary failure. Please retry later." It is reproducible by the following code:
var dcfc = new DataCacheFactoryConfiguration
{
Servers = new[] {new DataCacheServerEndpoint("localhost", 22233)},
SecurityProperties = new DataCacheSecurity(DataCacheSecurityMode.None, DataCacheProtectionLevel.None),
};
var dcf = new DataCacheFactory(dcfc);
var dc = dcf.GetDefaultCache();
const string key = "a";
var value = new int [256 * 1024]; // 1MB
for (int i = 0; i < 300; i++)
{
var putT = new Thread(() => dc.Put(key, value));
putT.Start();
var getT = new Thread(() => dc.Get(key));
getT.Start();
}
When calling Get() with different key or DataCache is synchronized, this issue will not appear. If DataCache is obtained with each call from DataCacheFactory (DataCache is supposed to be thread-safe) or timeouts are prolonged it has no effect and error is still received.
It seems to me very strange that MS would leave such bug. Did anybody faced similar issue?
I also see the same behavior and my understanding is that this is by design. The cache contains two concurrency models:
Optimistic Concurrency Model methods: Get, Put, ...
Pessimistic Concurrency Model: GetAndLock, PutAndLock, Unlock
If you use optimistic concurrency model methods like Get then you have to be ready to get DataCacheErrorCode.RetryLater and handle that appropriately - I also use a retry approach.
You might find more information at MSDN: Concurrency Models
We have seen this problem as well in our code. We solve this by overloading the Get method to catch expections and then retry the call N times before fallback to a direct request to SQL.
Here is a code that we use to get data from the cache
private static bool TryGetFromCache(string cacheKey, string region, out GetMappingValuesToCacheResult cacheResult, int counter = 0)
{
cacheResult = new GetMappingValuesToCacheResult();
try
{
// use as instead of cast, as this will return null instead of exception caused by casting.
if (_cache == null) return false;
cacheResult = _cache.Get(cacheKey, region) as GetMappingValuesToCacheResult;
return cacheResult != null;
}
catch (DataCacheException dataCacheException)
{
switch (dataCacheException.ErrorCode)
{
case DataCacheErrorCode.KeyDoesNotExist:
case DataCacheErrorCode.RegionDoesNotExist:
return false;
case DataCacheErrorCode.Timeout:
case DataCacheErrorCode.RetryLater:
if (counter > 9) return false; // we tried 10 times, so we will give up.
counter++;
Thread.Sleep(100);
return TryGetFromCache(cacheKey, region, out cacheResult, counter);
default:
EventLog.WriteEntry(EventViewerSource, "TryGetFromCache: DataCacheException caught:\n" +
dataCacheException.Message, EventLogEntryType.Error);
return false;
}
}
}
Then when we need to get something from the cache we do:
TryGetFromCache(key, region, out cachedMapping)
This allows us to use Try methods that encasulates the exceptions. If it returns false, we know thing is wrong with the cache and we can access SQL directly.