Hi there ( sorry if my english is not perfect...).
QUESTION: How to work with pthread and ncurses screen asynchronously...
I am writting a C++ UI lib that is based on NCurses. All the drawing/colors/mouse(gpm) are ok.
But using some of my objects in async multi-threaded mode, I have discovered that ncurses lib "getch()" blocks
calls to the addch.. familly, until input events ( from getch() such as mouse or keyboard or term resize ) occurs. I use blocked getch() in the main thread obviously because I want the main thread to sleep to not use 99% of the CPU).
I do my own window/clipping myself. I use only the stdscr WINDOW.
Notice that I am relatively new to NCurses AND pthread
Since I want to quikcly test my programming steps, here below some peace of code for the situation:
( few copy/paste )
...
<pre> ... oops seems format output doesn't work -- sorry for non indented code beliow :-(
class CTimer public CObject{
...
public:
// Start: creates the thread th_id then run it ...
bool Start(bool oneshot=false, bool destroy_thread=false);
private:
pthread_t th_id;
unsigned int _interval;
friend void* th_enter(void*);
bool _once;
bool _th_destroy;
...
...};
// Implementation (relevant for this subject
namespace ncx {
void* th_enter(void* t)
{
NEvent E; // The event data structure
CTimer* T = (CTimer*)t;
while(!T->_destroy_th){
usleep(T->_interval);
E._sender = T;
E.evID = NTIMER_EVENT;
if(T->bActive){
T->ActivateEvent(&E); // Send the timeout event.
++T->count;
}
T->bActive = !T->_once;
}
pthread_exit((void*) 0l);
}
CTimer::~CTimer()
{
UnRegisterEvent( NTIMER_EVENT );
pthread_cancel(th_id);
}
/*!
\fn ncx::CTimer::Start(bool oneshot=false, bool th_Destroy=false)
*/
bool CTimer::Start(bool oneshot, bool th_Destroy)
{
_once = oneshot;
_destroy_th = th_Destroy;
bActive = true;
pthread_create(&th_id, 0l, th_enter, (void*)this);
}
}; // namespace ncx;
and the application code that propagates the events:
...
void CApplication::ActivateEvent(CObject* _sender, NEvent* E)
{
_evID* id = _evIDNode(E->evID);
_evMap* idc;
CObject* O;
if(! id ) return;
// Validate sender object of the event:
if(( idc = hasSender(id, _sender)) ==0l)
return;
nodelay(stdscr, true);// this is a try to break the blocking state of ncurses::getch(); -- no success
E->_sender = _sender;
// propagate the event to client objects;
evclients_t clist = idc->_Clients;
if( clist.empty() ) return;
for (list<CObject*>::iterator IT = clist.begin(); IT != clist.end(); IT++){
O = *IT;
// Object must return "false" to abort the propagation of this event.
if(O->ProcessEvent(E)) break; // my label::ProcessEvent() get called.
}
nodelay(stdscr,false); // restore the blocking ncurses::getch();
return;
// It does not work async.
}
---------------------------------------
</pre>
So, let say I create a CTimer instance and bind it to a Label-widget object to show the current time on the screen, every 1 000 000 usleep units ( one second ...I think...).
Then a Label::ProcessEvent(my CTimer event) get called from my application event manager and then the label widget updates its drawing area with the time. In Fact it is doing it but ncurses::getch() blocks the screen update ( addch() ) .
I hope my problem is clearly described.
Thanks.