I am trying to re-write the classic producer-consumer algorithm using Windows libraries in C++. The snipped below was copied from a Java sample. Anyone know the equivalent of lock.notify and lock.wait using Windows Libraries such as EnterCriticalSection?
private Object lock = new Object();
public void produce() throws InterruptedException {
int value = 0;
while (true)
{
synchronized (lock)
{
while(list.size() == LIMIT)
{
lock.wait();
}
list.add(value++);
lock.notify();
}
}
thx!
Related
Until now I've only implemented synchronous node-addon-api methods, i.e., a JavaScript function makes a call, work is done, and the addon returns. I have big gaps in knowledge when it comes to the inner workings of v8, libuv, and node, so please correct any obvious misconceptions.
The goal is to call a JavaScript callback when C++ garbage collection callbacks are called from v8. I originally just called the JavaScript callback from the v8 garbage collection callback but that ended up with a segv after a couple calls. It seems that just making a call into JavaScript while being called from a v8 callback has some problems (v8 docs the callbacks shouldn't allocate objects). So I looked around and found a Nan-based example that uses libuv and Nan's AsyncResource to make the callback. The following approach works using node-nan:
NAN_GC_CALLBACK(afterGC) {
uint64_t et = uv_hrtime() - gcStartTime;
// other bookkeeping for GCData_t raw.
if (doCallbacks) {
uv_async_t* async = new uv_async_t;
GCData_t* data = new GCData_t;
*data = raw;
data->gcTime = et;
async->data = data;
uv_async_init(uv_default_loop(), async, asyncCB);
uv_async_send(async);
}
}
class GCResponseResource : public Nan::AsyncResource {
public:
GCResponseResource(Local<Function> callback_)
: Nan::AsyncResource("nan:gcstats.DeferredCallback") {
callback.Reset(callback_);
}
~GCResponseResource() {
callback.Reset();
}
Nan::Persistent<Function> callback;
};
static GCResponseResource* asyncResource;
static void closeCB(uv_handle_t *handle) {
delete handle;
}
static void asyncCB(uv_async_t *handle) {
Nan::HandleScope scope;
GCData_t* data = static_cast<GCData_t*>(handle->data);
Local<Object> obj = Nan::New<Object>();
Nan::Set(obj, Nan::New("gcCount").ToLocalChecked(),
Nan::New<Number>((data->gcCount));
Nan::Set(obj, Nan::New("gcTime").ToLocalChecked(),
Nan::New<Number>(data->gcTime));
Local<Object> counts = Nan::New<v8::Object>();
for (int i = 0; i < maxTypeCount; i++) {
if (data->typeCounts[i] != 0) {
Nan::Set(counts, i, Nan::New<Number>(data->typeCounts[i]));
}
}
Nan::Set(obj, Nan::New("gcTypeCounts").ToLocalChecked(), counts);
Local<Value> arguments[] = {obj};
Local<Function> callback = Nan::New(asyncResource->callback);
v8::Local<v8::Object> target = Nan::New<v8::Object>();
asyncResource->runInAsyncScope(target, callback, 1, arguments);
delete data;
uv_close((uv_handle_t*) handle, closeCB);
}
My question is how would I do this using the node-addon-api instead of nan?
It's not clear to me what the node-addon-api equivalent of uv_async_init, uv_async_send, etc are. This is partially because it's not clear to me what underlying N-API (as opposed to node-addon-api) functions are required.
I have been unable to find an example like this. The callback example is completely synchronous. The async pi example uses a worker thread to perform a task but that seems overkill compared to the approach in the nan-based code using the uv primitives.
Your example is not really asynchronous, because the GC callbacks run in the main thread. However when the JS world is stopped because of the GC, this does not mean that it is stopped in a way allowing a callback to run - as the GC can stop it in the middle of a function.
You need a ThreadSafeFunction to do this. Look here for an example:
https://github.com/nodejs/node-addon-api/blob/main/doc/threadsafe_function.md
I am working on a C++ project, which uses Google Pub/Sub.
As there is no native support for Google Pub/Sub in C++, I am using it through gRPC. Thus, I have generated corresponding pubsub.grpc.pb.h, pubsub.grpc.pb.cc, pubsub.pb.h and pubsub.pb.cc files via protoc.
I wrote a lightweight wrapper-class, for subscription management. Class basically creates a new thread and starts listening for new messages. Here is the code example (code was built based on this question):
class Consumer
{
public:
Consumer();
~Consumer();
void startConsume();
// ...
std::string m_subscriptionName;
std::unique_ptr<std::thread> m_thread;
std::shared_ptr<grpc::Channel> m_channel;
std::unique_ptr<google::pubsub::v1::Subscriber::Stub> m_stub;
std::atomic<bool> m_runThread;
};
Consumer::Consumer()
{
m_channel = grpc::CreateChannel("pubsub.googleapis.com:443", grpc::GoogleDefaultCredentials());
m_stub = google::pubsub::v1::Subscriber::NewStub(m_channel);
m_subscriptionName = "something";
}
Consumer::~Consumer()
{
m_runThread = false;
if (m_thread && m_thread->joinable())
{
m_thread->join();
}
}
void Consumer::startConsume()
{
m_thread.reset(new std::thread([this]()
{
m_runThread = true;
while (m_runThread)
{
grpc::ClientContext context;
std::unique_ptr<grpc::ClientReaderWriter<google::pubsub::v1::StreamingPullRequest,
google::pubsub::v1::StreamingPullResponse>> stream(m_stub->StreamingPull(&context));
// send the initial message
google::pubsub::v1::StreamingPullRequest req;
req.set_subscription(m_subscriptionName);
req.set_stream_ack_deadline_seconds(10);
// if write passed successfully, start subscription
if (!stream->Write(req))
{
continue;
}
// receive messages
google::pubsub::v1::StreamingPullResponse response;
while (stream->Read(&response))
{
google::pubsub::v1::StreamingPullRequest ack_request;
for (const auto& message : response.received_messages())
{
// process messages ...
ack_request.add_ack_ids(message.ack_id());
}
stream->Write(ack_request);
}
}
}));
}
Several instances of the Consumer class are created within a process.
It seems works fine. However sometimes program stucks on stream->Read(&response)code. Debugging showed that thread was stuck inside of Read() function call - the stream does not read anything and does not exit from function either, despite that Pub/Sub buffer is not empty. After restarting the application, all messages are successfully read. It seems like a deadlock inside of Read().
Is there anything that I am doing wrong? What can cause this behavior?
This is some code i'm using in Java for Making Asynchronous function calls in Java :
public class AsyncLogger
{
public static asyncLog = null;
public static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static AsyncLogger GetAsyncClass()
{
if(asyncLog == null)
{
asyncLog= new AsyncLogger();
}
return asyncLog;
}
public void WriteLog(String logMesg)
{
executorService.execute(new Runnable()
{
public void run()
{
WriteLogDB(logMesg);
}
});
}
public void ShutDownAsync()
{
executorService.shutdown();
}
}
This is a Singleton Class with static ExecutorService and WriteLogDB will be called as an Asynchronous function. So i can process my Code in WriteLogDB asynchronously without affecting the main flow.
Can i get a C++ equivalent like this ..?
std::thread([](){WriteLogDB(logMesg);}).detach();
or if you need to wait for a result:
auto result = std::async(std::launch::async, [](){WriteLogDB(logMesg);});
// do stuff while that's happening
result.get();
If you're stuck with a pre-2011 compiler, then there are no standard thread facilities; you'll need to use a third-party library like Boost, or roll you own, platform specific, threading code. Boost has a thread class similar to the new standard class:
boost::thread(boost::bind(WriteLogDB, logMesg)).detach();
You can make asynchronous functions calls using std::async from C++11.
I found a threadpool which doesn't seem to be in boost yet, but I may be able to use it for now (unless there is a better solution).
I have several million small tasks that I want to execute concurrently and I wanted to use a threadpool to schedule the execution of the tasks. The documentation of the threadpool provides (roughly) this example:
#include "threadpool.hpp"
using namespace boost::threadpool;
// A short task
void task()
{
// do some work
}
void execute_with_threadpool(int poolSize, int numTasks)
{
// Create a thread pool.
pool tp(poolSize);
for(int i = 0; i++; i < numTasks)
{
// Add some tasks to the pool.
tp.schedule(&task);
}
// Leave this function and wait until all tasks are finished.
}
However, the example only allows me to schedule non-member functions (or tasks). Is there a way that I can schedule a member function for execution?
Update:
OK, supposedly the library allows you to schedule a Runnable for execution, but I can't figure out where is the Runnable class that I'm supposed to inherit from.
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj);
Update2:
I think I found out what I need to do: I have to make a runnable which will take any parameters that would be necessary (including a reference to the object that has a function which will be called), then I use the static schedule function to schedule the runnable on the given threadpool:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
Here is how I schedule it within MyClass:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
However, the adaptor from the library has a bug in it:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
Note that it takes a reference to a Pool but it tries to call it as if it was a pointer to a Pool, so I had to fix that too (just changing the -> to a .).
To schedule any function or member function - use Boost.Bind or Boost.Lambda (in this order). Also you can consider special libraries for your situation. I can recommend Inter Threading Building Blocks or, in case you use VC2010 - Microsoft Parallel Patterns Library.
EDIT:
I've never used this library or heard anything bad about it, but it's old enough and still is not included into Boost. I would check why.
EDIT 2:
Another option - Boost.Asio. It's primarily a networking library, but it has a scheduler that you can use. I would use this multithreading approach. Just instead of using asynchronous network operations schedule your tasks by boost::asio::io_service::post().
I think I found out what I need to do: I have to make a runnable which will take any parameters that would be necessary (including a reference to the object that has a function which will be called), then I use the static schedule function to schedule the runnable on the given threadpool:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
Here is how I schedule it within MyClass:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
However, the adaptor from the library has a bug in it:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
Note that it takes a reference to a Pool but it tries to call it as if it was a pointer to a Pool, so I had to fix that too (just changing the -> to a .).
However, as it turns out, I can't use that boost thread pool because I am mixing native C++ (dll), C++/CLI (dll) and .NET code: I have a C++/CLI library that wraps a native C++ library which in tern uses boost::thread. Unfortunately, that results in a BadImageFormatException at runtime (which has previously been discussed by other people):
The problem is that the static boost thread library tries to hook the
native win32 PE TLS callbacks in order to ensure that the thread-local
data used by boost thread is cleaned up correctly. This is not
compatible with a C++/CLI executable.
This solution is what I was able to implement using the information: http://think-async.com/Asio/Recipes. I tried implementing this recipe and found that the code worked in Windows but not in Linux. I was unable to figure out the problem but searching the internet found the key which was make the work object an auto pointer within the code block. I've include the void task() that the user wanted for my example I was able to create a convenience function and pass pointers into my function does the work. For my case, I create a thread pool that uses the function : boost::thread::hardware_concurrency() to get the possible number of threads. I've used the recipe below with as many as 80 tasks with 15 threads.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
// A short task
void task()
{
// do some work
}
void execute_with_threadpool( int numTasks,
int poolSize = boost::thread::hardware_concurrency() )
{
boost::asio::io_service io_service;
boost::thread_group threads;
{
boost::scoped_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(io_service) );
for(int t = 0; t < poolSize; t++)
{
threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
}
for( size_t t = 0; t < numTasks; t++ )
{
++_number_of_jobs;
io_service.post(boost::bind(task) );
}
}
threads.join_all();
}
Figured it out, you must have run() method defined, this is the easiest way:
class Command
{
public:
Command() {}
~Command() {}
void run() {}
};
In main(), tp is your threadpool:
shared_ptr<Command> pc(new Command());
tp.schedule(bind(&Command::run, pc));
Done.
I'm writing a multithreaded app.
I was using the boost::interprocess classes (version 1.36.0)
Essentially, I have worker threads that need to be notified when work is available for them to do.
I tried both the "semaphore" and "condition" approaches.
In both cases, the CSwitch (context switch) for the worker threads seemed very high, like 600 switches per second.
I had a gander at the code and it seems like it just checks a flag (atomically using a mutex) and then yields the timeslice before trying again next time.
I was expecting the code to use WaitForSingleObject or something.
Ironically, this was exactly how I was doing it before deciding to do it "properly" and use Boost! (i.e. using a mutex to check the status of a flag regularly). The only difference was, in my approach I was sleeping like 50ms between checks so I didn't have the high CSwitch problem (and yes it's fine for me that work won't start for up to 50ms).
Several questions:
Does this "high" CSwitch value matter?
Would this occur if the boost library was using CRITICAL_SECTIONS instead of semaphores (I don't care about inter-process syncing - all threads are in same process)?
Would this occur if boost was using WaitForSingleObject?
Is there another approach in the Boost libs that uses the aforementioned Win32 wait methods (WaitForXXX) which I assume won't suffer from this CSwitch issue.
Update: Here is a pseudo code sample. I can't add the real code because it would be a bit complex. But this is pretty much what I'm doing. This just starts a thread to do a one-off asynchronous activity.
NOTE: These are just illustrations! There is loads missing from this sample, e.g. if you call injectWork() before the thread has hit the "wait" it just won't work. I just wanted to illustrate my use of boost.
The usage is something like:
int main(int argc, char** args)
{
MyWorkerThread thread;
thread.startThread();
...
thread.injectWork("hello world");
}
Here is the example using boost.
class MyWorkerThread
{
public:
/// Do work asynchronously
void injectWork(string blah)
{
this->blah = blah;
// Notify semaphore
this->semaphore->post();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
// Wait for semaphore to be invoked
semaphore->wait();
cout << blah << endl;
}
string blah;
boost::interprocess::interprocess_semaphore* semaphore;
};
And here was my "naive" polling code:
class MyWorkerThread_NaivePolling
{
public:
MyWorkerThread_NaivePolling()
{
workReady = false;
}
/// Do work asynchronously
void injectWork(string blah)
{
section.lock();
this->blah = blah;
this->workReady = true;
section.unlock();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
/// Uses Win32 CriticalSection
class MyCriticalSection
{
MyCriticalSection();
void lock();
void unlock();
};
MyCriticalSection section;
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
while (true)
{
bool myWorkReady = false;
string myBlah;
// See if work set
section.lock();
if (this->workReady)
{
myWorkReady = true;
myBlah = this->blah;
}
section.unlock();
if (myWorkReady)
{
cout << blah << endl;
return;
}
else
{
// No work so sleep for a while
Sleep(50);
}
}
}
string blah;
bool workReady;
};
Cheers,
John
On non-POSIX systems, it seems that interprocess_condition is emulated using a loop, as you describe in your in question. And interprocess_semaphore is emulated with a mutex and an interprocess_condition, so wait()-ing ends up in the same loop.
Since you mention that you don't need the interprocess synchronization, you should look at Boost.Thread, which offers a portable implementation of condition variables. Amusingly, it seems that it is implemented on Windows in the "classical" way, using a... Semaphore.
If you do not mind a Windows specific (newer versions on windows), check the link for light weight condition variables CONDITION_VARIABLE (like critical sections):