Is Poco::Logger threadsafe? - c++

It seems like threadsafe in my test code below. Can I use Poco::Logger in a multithreaded program?
static Poco::Logger *pLogger;
class MyRunnable : public Poco::Runnable {
private:
std::string _name;
Poco::Random _rnd;
public:
void setName(std::string name) {
_name = name;
}
void run() {
for (int i=0; i<200; i++) {
pLogger->information("info from: " + _name);
_rnd.seed(_rnd.next(65532) * _name.size());
Poco::Thread::sleep(_rnd.next(13) + 1);
}
}
};
here is test main:
int
main ( int argc, char *argv[] )
{
Poco::Thread thr1, thr2, thr3;
MyRunnable *pMyR1 = new MyRunnable(),
*pMyR2 = new MyRunnable(),
*pMyR3 = new MyRunnable();
pMyR1->setName("r1");
pMyR2->setName("ra2");
pMyR3->setName("runable3");
Poco::FormattingChannel *pFCFile = new Poco::FormattingChannel(new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S.%c %N[%P]:%s: %q:%t"));
pFCFile->setChannel(new Poco::FileChannel("test.log"));
pFCFile->open();
pLogger = &(Poco::Logger::create("FileLogger", pFCFile, Poco::Message::PRIO_INFORMATION));
thr1.start(*pMyR1);
thr2.start(*pMyR2);
thr3.start(*pMyR3);
std::cout << "starting..." << std::endl;
thr1.join();
thr2.join();
thr3.join();
std::cout << "end." << std::endl;
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */

This question is very old, but I had the same doubt, so looking on the library Forum I found:
http://pocoproject.org/forum/viewtopic.php?f=12&t=1233&p=2681&hilit=logger#p2681
The important quotation is: "The Logger is thread safe regarding the different logging function. If you try to change the Channel connected to a Logger while another thread is currently using the Logger, this may lead to problems."

Related

Why does loading a block of memory from a DLL only crash at the second call to memmove?

This is the class in question (only functions that pertain to this question) and everything it depends on (all written myself). It provides an interface to a DLL.
struct MemRegion {
const uint64_t address;
const uint64_t size;
};
enum Version {
VERSION_US,
VERSION_JP
};
const struct MemRegion SEGMENTS[2][2] = {
{{1302528, 2836576},
{14045184, 4897408}},
{{1294336, 2406112},
{13594624, 4897632}},
};
using Slot = array<vector<uint8_t>, 2>;
class Game {
private:
Version m_version;
HMODULE m_dll;
const MemRegion* m_regions;
public:
Game(Version version, cstr dll_path) {
m_version = version;
m_dll = LoadLibraryA(dll_path);
if (m_dll == NULL) {
unsigned int lastError = GetLastError();
cerr << "Last error is " << lastError << endl;
exit(-2);
}
// this is a custom macro which calls a function in the dll
call_void_fn(m_dll, "sm64_init");
m_regions = SEGMENTS[version];
}
~Game() {
FreeLibrary(m_dll);
}
void advance() {
call_void_fn(m_dll, "sm64_update");
}
Slot alloc_slot() {
Slot buffers = {
vector<uint8_t>(m_regions[0].size),
vector<uint8_t>(m_regions[1].size)
};
return buffers;
}
void save_slot(Slot& slot) {
for (int i = 0; i < 2; i++) {
const MemRegion& region = m_regions[i];
vector<uint8_t>& buffer = slot[i];
cerr << "before memmove for savestate" << endl;
memmove(buffer.data(), reinterpret_cast<void* const>(m_dll + region.address), region.size);
cerr << "after memmove for savestate" << endl;
}
}
};
When I call save_slot(), it should copy two blocks of memory to a couple of vector<uint8_t>s. This does not seem to be the case, though. The function finishes the first copy, but throws a segmentation fault at the second memcpy. Why does it only happen at the second copy, and how can I get around this sort of issue?
Edit 1: This is what GDB gives me when the program terminates:
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ffac2164452 in msvcrt!memmove () from C:\Windows\System32\msvcrt.dll
Edit 2: I tried accessing the segments individually. It works, but for some reason, I can't access both segments in the same program.
I found out that HMODULE is equivalent to void*. Since you can't really use pointer arithmetic on void*s, you have to cast it to a uint8_t* or equivalent to properly get an offset.
Here's what that looks like in practice:
void save_state(Slot& slot) {
uint8_t* const _dll = (uint8_t*)((void*)m_dll);
for (int i = 0; i < 2; i++) {
MemRegion segment = m_regions[i];
std::vector<uint8_t>& buffer = slot[i];
memmove(&buffer[0], _dll + segment.address, segment.size);
}
}

Segmentation fault (core dumped) using stringstream in multithread application

I trying do simple threadsafe logger, which print messages to console.
// Test function for check logger. It is work
void test(double& diff)
{
std::vector<double> result;
for( int counter = 0; counter < 100000; ++counter)
{
result.push_back(clock());
std::string text = "counter = ";
text.append(std::to_string(counter));
LOG_MESSAGE(text); //<-- Correct log..
}
diff = clock() - result.front();
}
int main(int argc, char** argv)
{
double time2;
double time1;
std::vector<double> timerResult;
std::vector<std::thread> threadVector;
time1 = clock();
for(int i = 0; i < 5; ++i) //<-- Create 5 thread of test function
{
timerResult.push_back(0);
threadVector.push_back(std::thread(test, std::ref(timerResult[i])));
}
for(std::thread& t : threadVector)
t.join();
time2 = clock(); //<-- Threads is finished
double res = 0;
for(double tRes : timerResult)
res += tRes;
res = res / static_cast<double>(CLOCKS_PER_SEC);
std::string message; //<-- Generate final message
message.append("Timer: ")
.append(std::to_string((time2 - time1) / (double)CLOCKS_PER_SEC))
.append(" - thread timer: ")
.append(std::to_string(res));
LOG_MESSAGE(message); //<-- Crash inside!!
return 0;
}
Logger is good working in threads. But when I try log in main() function that call SIGSEGV signal in destructor of std::ostringstream (in function of construct log message):
static Logger::Core logger; //<--Global Logger variable
#define LOG_MESSAGE( TEXT ) logger.addNoteInLog(TEXT) //<-- Define for log message
void Core::addNoteInLog(const Message &message) //<-- threadsafe log function
{
std::string text;
message.generateString(text); //<-- [Crash here] generate log message
g_lock.lock();
std::cout << text;
g_lock.unlock();
}
void Message::generateString(std::string& text) const
{
text.clear();
tm *ltm = localtime(&mDate);
std::ostringstream data; //<-- [Crash here] function is finished, but cannot destruct object.
data << 1900 + ltm->tm_year << "/"
<< 1 + ltm->tm_mon << "/"
<< ltm->tm_mday << "\t";
data << "[INF] - ";
data << std::this_thread::get_id() << " - "
<< mMessage << "\n";
text = data.str();
}
I dont understand why logger in threads is work, but in main() function crashed. Using the exclusion method, I found out when the error is occurred:
when I use 5 (or more) threads
when test function is not empty
when in generateString use stringstream or ostringstream or string.append() (in last case application crash in std::string destructor in same place)
What say debugger in QtCreater.
Build in Ubuntu OS, gcc version 5.4.0, compilation flags: -std=c++17 -pthread -Wall
This is my git repository with error.
Problem solved.
As it was said in the comments, line threadVector.push_back(std::thread(test, std::ref(timerResult[i]))); is not correct, because memory reallocation in timerResult was done after calling push_back 5 times, and passing reference by ref(timerResult[i]) is incorrect.
Correct code:
int main(int argc, char** argv)
{
double time2;
double time1;
std::vector<double> timerResult (5); //<-- Create filling of vector
std::vector<std::thread> threadVector;
time1 = clock();
for(int i = 0; i < 5; ++i)
{
//timerResult.push_back(0); //<-- incorrect filling of vector
threadVector.push_back(std::thread(test, std::ref(timerResult[i])));
}
for(std::thread& t : threadVector)
t.join();
time2 = clock();
...
}

C++ -- Join a vector of threads [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using g++ 4.8 to write a c++11 program. I'm trying to convert a single threaded program to multi-threaded one. The join in the threaded version ends up throwing a compilation error. Could you please let me know where I'm going wrong?
Single Threaded(works well):
Note that all arguments are pass by reference.
for (const auto& i : vec_clients)
{
i->startSim(vec_masters, vec_trace1, vec_trace2, vec_trace3);
}
Multi-Threaded version:
std::vector<std::thread> vec_thr;
for (const auto& i : vec_clients)
{
std::thread t1(&Client::startSim, std::move(i), std::move(vec_trace1), std::move(vec_trace2), std::move(vec_trace3));
vec_thr.push_back(std::move(t1));
}
for (unsigned int i=0; i<vec_thr.size(); ++i)
{
// if (i.joinable())
vec_thr.at(i).join();
}
Modified(simpler example):
class Test
{
private:
public:
void testme(const std::string& _str)
{
std::cout << "Hello "+_str << std::endl;
}
};
int main(const int argc, const char **argv)
{
std::string str = "there";
Test t1;
std::vector<std::thread> vec_thr;
std::thread thr1(&Test::testme, std::move(t1), std::cref(str));
vec_thr.push_back(thr1);
return 0;
}
Integer i does not have a joinable member function (or any member function as it is a primitive type). It should be:
for (unsigned int i=0; i<vec_thr.size(); ++i)
{
if (vec_thr[i].joinable())
vec_thr.at(i).join();
}
Or just use join on the thread. I see no particular reason to do joinable test here as you are not detaching any of the threads.
In case anyone is still interested, this is the answer:
class Test
{
private:
public:
void testme(const std::string& _str)
{
std::cout << "Hello "+_str << std::endl;
}
void testme2(const std::string& _str)
{
std::cout << "Hello to "+_str << std::endl;
}
};
int main(const int argc, const char **argv)
{
std::string str = "there";
std::unique_ptr<Test> up1(new Test());
std::unique_ptr<Test> up2(new Test());
std::vector<std::thread> vec_thr;
std::thread thr1(&Test::testme, std::move(up1), std::ref(str));
std::thread thr2(&Test::testme2, std::move(up2), std::ref(str));
vec_thr.push_back(std::move(thr1));
vec_thr.push_back(std::move(thr2));
for (unsigned int i=0; i<vec_thr.size(); ++i)
{
vec_thr.at(i).join();
}
return 0;
}

Create properties and methods Lua C++

This is rather tricky to explain and I could not find anything on this in the documentation or anywhere on the net so I thought this would be a suitable place for this question.
I'm trying to register properties and methods on an object in Lua using C++.
This is what I'm trying to achieve in Lua:
player = createPlayer()
player:jump() // method
player.x = player.x + 3 // properties
I can easily achieve the first line in the example using C++
int create_player(lua_State *L)
{
Player* player = new Player();
..
return 0;
}
int main(int args, char * argv[])
{
lua_State* L = lua_open();
luaL_openlibs(L);
lua_register(L, "createPlayer", create_player);
luaL_dofile(L, "main.lua");
..
return 0;
}
But how do I create the method :jump() and properties .setX and .getX for createPlayer?
What you could have searched is "Binding C++ to Lua".
Since it's a rather popular question, I'll post an answer with a project compilable online:
Starting from a C++ class:
class Player {
int x;
public:
Player() : x(0) {}
int get_x() const { return x; }
void set_x(int x_) { x = x_; }
void jump() {}
};
You can then create bindings using LuaBridge without writing the boilerplate for each of the bound members yourself:
void luabridge_bind(lua_State *L) {
luabridge::getGlobalNamespace(L)
.beginClass<Player>("Player")
.addConstructor<void (*)(), RefCountedPtr<Player> /* shared c++/lua lifetime */ >()
.addProperty("x", &Player::get_x, &Player::set_x)
.addFunction("jump", &Player::jump)
.endClass()
;
}
Using a dedicated Lua State wrapper LuaState, you can then open a Lua state and perform the bindings:
lua::State state;
luabridge_bind(state.getState());
Running the script using some trace output:
try {
static const char *test =
"player = Player() \n"
"player:jump() \n"
"player.x = player.x + 3"
;
state.doString(test);
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
Produces the following output:
Player
jump
get_x
set_x 3
~Player
You can see the whole thing live at Travis-CI

Making an event like subscribing system for C++ * chars

For simple data like ints or constants something like this would work
#include <iostream>
#include <vector>
using namespace std ;
typedef void FuncInt (int) ;
class GraphElementProto {
public:
void add (FuncInt* f)
{
FuncVec.push_back (f) ;
} ;
void call()
{
for (size_t i = 0 ; i < FuncVec.size() ; i++)
FuncVec[i] (i) ;
} ;
private:
vector<FuncInt*> FuncVec ;
} ;
static void f0 (int i) { cout << "f0(" << i << ")" << endl ; }
static void f1 (int i) { cout << "f1(" << i << ")" << endl ; }
int main() {
GraphElementProto a ;
a.add (f0) ;
a.add (f1) ;
a.call() ;
}
So now imagine we work with some data buffer like char.
We have threads that wait for data pointers and on appearance of that pointers want to change data at the same time. So we would need to create copy's of that data and give to each subscriber pointer to his own copy.
So how to do such thing? (sorry C++ nube - code is only thing I can understand)
Consider the similarities between each node of the graph that you describe and create a class for them (class GraphElement below). It should encapsulate its relationship to its child nodes, and it should do something locally with any incoming messages (function localAction). You should then derive classes that represent specific variations - such as the image generator you mention - and change the local action. Each class may take a copy of the original message, or change it as you need.
In my example code here I have create the default graph node - GraphNode - and made it simply print incoming messages before passing them to its child nodes. I have used a string object for the incoming message - a lot nicer than a plain old C char * array [example: you can derive a string from char * when message2 is created in the code below]. I have made those object const references as its cheap, fast, and never changes the original.
I have derived a class called CatNode as an example of the variation you need. Objects of this type contain a history of all messages, and print out that history when a new message arrives. Not very useful - but a good example none the less. This demonstrates how each node may do anything to a copy of the original message - rewrite localAction(). It also passes that history to any child nodes - rewrite incomingMessage with a change to the parameter passed to deliverMessage().
#include <vector>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
class GraphNode
{
public:
GraphNode( string & name ) : mChildren(), mName(name) {}
GraphNode( const char * const name ) : mChildren(), mName(name==NULL?"":name) {}
virtual void incomingMessage( const string & str ) {
localAction(str); // This node is to do something.
deliverMessage(str); // Child nodes are to do things too.
}
void addChild( GraphNode * child ) {
mChildren.push_back( child );
}
protected:
// Rewrite this function for child classes who are to do different things with messages.
virtual void localAction( const string & str ) {
cout << mName << " : " << str << endl;
}
void deliverMessage( const string & str ) {
vector<GraphNode*>::iterator itr = mChildren.begin();
for( ; itr != mChildren.end(); ++itr )
(*itr)->incomingMessage(str);
}
// Data members
vector<GraphNode*> mChildren;
string mName;
}; // [ GraphNode ]
class CatNode : public GraphNode
{
public:
CatNode( string & name ) : GraphNode(name), mHistory() {}
CatNode( const char * const name ) : GraphNode(name), mHistory() {}
virtual void incomingMessage( const string & str ) {
localAction(str);
deliverMessage(mHistory);
}
protected:
virtual void localAction( const string & str ) {
mHistory += str;
cout << mName << " : " << mHistory << endl;
}
// Data members
string mHistory;
}; // [ CatNode ]
main()
{
// root -> childA
GraphNode root("Root Node");
CatNode childA("Child A");
root.addChild( &childA );
root.incomingMessage("Message1");
cout << endl;
// root -> childA -> childC
// \-> childB
GraphNode childB("Child B");
root.addChild( &childB );
GraphNode childC("Child C");
childA.addChild( &childC );
string message2("Message2");
root.incomingMessage(message2);
} // [ main ]