I have been trying to figure out how to ignore repeated keys in an xcb event loop and so far have got this:
extern xcb_connection_t *connection;
// looks like there's a leak, but in the finished product there isn't
bool poll_event(/*my_event_type e*/){
static xcb_generic_event_t *ev = nullptr;
static xcb_key_press_event_t *last_key_ev = nullptr;
if(!(ev = xcb_poll_for_event(connection)))
return false;
switch(ev->response_type & ~0x80){
case XCB_KEY_PRESS:{
xcb_key_press_event_t *kp = static_cast<decltype(kp)>(ev);
if(last_key_ev &&
((last_key_ev->response_type & ~0x80) == XCB_KEY_RELEASE) &&
(last_key_ev->detail == kp->detail) &&
(last_key_ev->time == kp->time)
){
std::free(last_key_ev);
last_key_ev = kp;
// is repeated key, ignore this event
return false;
}
std::free(last_key_ev);
last_key_ev = kp;
return true;
}
case XCB_KEY_RELEASE:{
/* same as KEY_PRESS but looking for KEY_PRESS in 'last_key_ev' */
}
default:
std::free(ev);
return true;
}
}
This doesn't work because it will only discard the second half of the repeated event pair (XCB_KEY_RELEASE then XCB_KEY_PRESS), so I get a bunch of XCB_KEY_RELEASE events rather than none. but there doesn't seem to be a function in xcb for testing if there is an event in the queue without modifying the queue itself.
I am looking for an XEventsQueued equivalent in xcb so I could test if there is an event queued straight afterward instead of using the last event that occured, but have failed to do so yet.
Have any of you done this already and be willing to pass on your wisdom in the matter?
So, #n.m said that XCB has no utility for peaking into the event queue. So I wrote my own wrapper over the xcb event queue so I could peak into the next event. Here is how I implemented it if anyone is interested:
First my event queue:
extern xcb_connection_t *connection;
struct my_event_queue_t{
xcb_generic_event_t *prev = nullptr;
xcb_generic_event_t *current = nullptr;
xcb_generic_event_t *next = nullptr;
} event_queue;
void update_event_queue(){
std::free(event_queue.prev);
event_queue.prev = event_queue.current;
event_queue.current = event_queue.next;
event_queue.next = xcb_poll_for_queued_event(connection);
}
Then the event loop:
struct my_event_type;
bool poll_event(my_event_type &ret){
static xcb_generic_event_t *xcb_ev = nullptr;
update_event_queue();
xcb_ev = event_queue.current;
if(!xcb_ev) return false;
switch(xcb_ev->response_type & ~0x80){
case XCB_KEY_RELEASE:{
static xcb_key_press_event_t *kp = nullptr;
kp = xcb_ev;
if(event_queue.next &&
((event_queue->response_type & ~0x80) == XCB_KEY_PRESS) &&
(reinterpret_cast<decltype(kp)>(xcb_ev)->time == kp->time) &&
(reinterpret_cast<decltype(kp)>(xcb_ev)->detail == kp->detail)
){
update_event_queue(); // eat repeat event
return false;
}
// update ret
return true;
}
case XCB_KEY_PRESS:{
// handle normally
// update ret
return true;
}
default:
// signify unknown event
return true;
}
}
This is how I ignore key repeats in my application, which is a toolkit for game/graphical application development. I haven't tested what sort of performance dip this gives, but it should be minimal.
Related
if (GetKeyState(VK_DOWN) & 0x80)
{
func();
}
It calls func() like 4 times when I press key
I want it to call only once when I press key
EDIT:
SHORT keyState;
SHORT keyState2;
SHORT keyState3;
static bool toogle1 = false;
static bool toogle2 = false;
static bool toogle3 = false;
if (keyState = GetAsyncKeyState(VK_DOWN) && !toogle1)
{
toogle1 = true;
}
else
toogle1 = !toogle1;
if (keyState2 = GetAsyncKeyState(VK_NUMPAD0) && !toogle2)
{
toogle2 = true;
}
else
toogle2 = !toogle2;
if (keyState3 = GetAsyncKeyState(VK_NUMPAD1) && !toogle3)
{
toogle3 = true;
}
else
toogle3 = !toogle3;
Here is how I did it, will it work?
static bool once = false;
if (GetKeyState(VK_DOWN) & 0x80)
{
if (!once)
{ once = true; func(); }
}
I guess you run this in a loop. Your idea with toggling a flag when called is not bad, but since you toggle it back in the else case, you call func() half as often as before (every 2nd time).
When you want to call it again (I think you want, according to your code), when the key is pressed again, but not spam the function call, you can use a variable to store which key was pressed last and only call func(), when it was another key (you can also add a "no key pressed" state.
If you really just want to call it once, just remove your else statements.
I cannot understand the meaning of this design.
When tryAccquire method is called,and it will return false when the lock is held by another thread, why not just addWaiter to sync queue and park this thread,waiting to be invoked?
In accquireQueued method ,the first thread node waiting is get out to tryAcquire again.I guess it will fail to acquire the lock very likely.
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
I am debugging an issue with WinDbg which I can consistently produce. The problem is when I run the executable with WinDbg to debug it, the issue can't be reproduced. What could be the reason?
Here is the code the behaves differently:
CWnd* pWnd = GetDlgItem(IDOKCANCEL);
if(pWnd)
{
CString sOK;
sOK.LoadString(IDS_OK);
pWnd->SetWindowText(sOK);
}
Here the button text is updated properly when I run with WinDbg but it is not updated when I run it normally (which is the bug).
Update
Like I said in comments, the issue is not with the code above because it's doesn't even get called. The operation is done in a worker thread which sends update messages to this dialog. The final message that executes the above code is never send do it so the above code is never executed.
Why the worker thread doesn't send this message is interesting. It ges locked on a critical section while opening a database. WinDbg tells me that the main thread is the owner of that critical section but I can't see from call stack or any other way where does it failed to unlock the critical section.
What complicates the problem is that it works fine if I run it with debugger. I added log output but it also starts to works fine with this change.
The only way I can catch it with a debugger is when I run it normal mode, produce the problem, then attach the debugger and it shows me its locked on the critical section. It shows the main thread is the owner of that critical section but it not clear why it is in locked state. The critical section is simply locked and unlocked in one function and its out of there.
Update 2
I am using the critical section only in one file in my entire project and there in only two functions (when it opens database and recordset).
BOOL CADODatabase::Open(LPCTSTR lpstrConnection, LPCTSTR lpstrUserID, LPCTSTR lpstrPassword)
{
CString database = GetSourceDatabase( lpstrConnection, NULL );
// get the appropriate critical section based on database
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
HRESULT hr = S_OK;
if(IsOpen())
Close();
if(wcscmp(lpstrConnection, _T("")) != 0)
m_strConnection = lpstrConnection;
ASSERT(!m_strConnection.IsEmpty());
try
{
if(m_nConnectionTimeout != 0)
m_pConnection->PutConnectionTimeout(m_nConnectionTimeout);
hr = m_pConnection->Open(_bstr_t(m_strConnection), _bstr_t(lpstrUserID), _bstr_t(lpstrPassword), NULL);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return hr == S_OK;
}
catch(_com_error &e)
{
dump_com_error(e);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
}
The 2nd function has other visible imperfections but please ignore that, its legacy code.
BOOL CADORecordset::Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec, int nOption)
{
BSTR bstrConnString;
m_pConnection->get_ConnectionString(&bstrConnString);
CString database = GetSourceDatabase( bstrConnString, m_pConnection );
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
Close();
if(wcscmp(lpstrExec, _T("")) != 0)
m_strQuery = lpstrExec;
ASSERT(!m_strQuery.IsEmpty());
if(m_pConnection == NULL)
m_pConnection = mpdb;
m_strQuery.TrimLeft();
BOOL bIsSelect = m_strQuery.Mid(0, _tcslen(_T("Select "))).CompareNoCase(_T("select ")) == 0 && nOption == openUnknown;
int maxRetries = 10;
bool bContinue = true;
CursorTypeEnum adCursorType = adOpenStatic;
if (!m_bSQLEngine)
{
// MDB Engine
adCursorType = adOpenStatic;
m_pConnection->CursorLocation = adUseClient;
}
else
{
// SQL Engine
adCursorType = adOpenDynamic;
m_pConnection->CursorLocation = adUseServer;
}
int currentCommandTimeout = m_pConnection->CommandTimeout;
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
for (int iRetry = 0; (iRetry < maxRetries) && bContinue; iRetry++)
{
try
{
// we just use an auto lock object so it is unlocked automatically, it uses same
// critical section object.
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
int newCommandTimeout = currentCommandTimeout + 15 * iRetry;
m_pConnection->CommandTimeout = newCommandTimeout;
if(bIsSelect || nOption == openQuery || nOption == openUnknown)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adCursorType, adLockOptimistic, adCmdUnknown);
}
else if(nOption == openTable)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adOpenDynamic, adLockOptimistic, adCmdTable);
}
else if(nOption == openStoredProc)
{
m_pCmd->ActiveConnection = mpdb;
m_pCmd->CommandText = _bstr_t(m_strQuery);
m_pCmd->CommandType = adCmdStoredProc;
m_pRecordset = m_pCmd->Execute(NULL, NULL, adCmdText);
}
else
{
TRACE( _T("Unknown parameter. %d"), nOption);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
bContinue = false;
}
catch(_com_error &e)
{
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
dump_com_error_without_exception(e, _T("Open"));
// retry Query timeout
CString szDescription;
_bstr_t bstrDescription(e.Description());
szDescription.Format( _T("%s"), (LPCTSTR)bstrDescription);
if ((szDescription.Find(_T("Query timeout expired")) == -1) || (iRetry == maxRetries - 1))
{
m_pConnection->CommandTimeout = currentCommandTimeout;
throw CADOException(e.Error(), e.Description());
}
Sleep (1000);
bContinue = true;
}
}
m_pConnection->CommandTimeout = currentCommandTimeout;
return m_pRecordset != NULL && m_pRecordset->GetState()!= adStateClosed;
}
For the sake of completeness, the above calls this function:
static CCriticalSection* GetDbCriticalSection(const CString& database)
{
// For now we only care about one database and its corresponding critical section
if (database.CompareNoCase( _T("Alr") ) == 0)
return &g_csAlrDb; // g_csAlrDb is defined static global in this file
else
return 0;
}
The Open() function gets called for various databases, I am only locking guarding access to one database. As you can see there is corresponding lock/unlocks so not sure how does code comes up of these functions leave th critical section locked. Could it be because of MFC issue?
In my case, most of the time, when C++ software behaves different between debug and release versions, it's because of uninitialized variables, different libraries linked, or compiler optimizations backfiring.
To trace the bug, try evaluating variables and function return values, i.e. LoadString, for example with AfxMessageBox().
I am using xlib to get keyboard input I want to simulate windows its getAsynckeystate() to check if a button is being pressed I tried using a timer to fix the result but its still broken. the function should always return true if 'z' is held down even if other keys are pressed or released at the same time (not working right now)
Code below
bool KeyboardState::keyPressed(Display* d, Window curFocus,int revert, Window root) {
XEvent ev;
XNextEvent(d, &ev);
clock_t startTime;
switch (ev.type) {
case FocusOut:
if (curFocus != root)
XSelectInput(d, curFocus, 0);
XGetInputFocus(d, &curFocus, &revert);
printf("New focus is %d\n", (int) curFocus);
if (curFocus == PointerRoot)
curFocus = root;
XSelectInput(d, curFocus, KeyReleaseMask | FocusChangeMask | KeyPressMask);
break;
case KeyPress:
ks = XLookupKeysym(&(ev.xkey), 0);
if (ks == XK_z) {
keyState = true;
startTime = clock();
}
break;
case KeyRelease:
if(ks == XK_z && startTime - clock() > 0){
ks = XLookupKeysym(&(ev.xkey), 0);
keyState = false;
}
}
return keyState;
}
n.m linked following function which is accepted as answer:
tronche.com/gui/x/xlib/input/XQueryKeymap.html
I wrote the following code snippet to help do keyboard shortcuts with multiple non-modifier keys e.g. super + up + right.
#include <X11/Xlib.h>
// Returns 0 if key is not down;
// A non-zero integer if it is down.
// targetString should be appropriate for XStringToKeysym.
int is_down(Display *dis, char *targetString)
{
char keys_return[32] = {0};
KeySym targetSym = XStringToKeysym(targetString);
KeyCode targetCode = XKeysymToKeycode(dis, targetSym);
int targetByte = targetCode / 8;
int targetBit = targetCode % 8;
int targetMask = 0x01 << targetBit;
XQueryKeymap(dis, keys_return);
return keys_return[targetByte] & targetMask;
}
I've posted a more complete example with compilation instructions on GitHub. You can find a complete list of key names in a file named X11/keysymdef.h; on my Arch computer it was at /usr/include/X11/keysymdef.h. I also found an example on the web as the second Google result for x11 keysymdef.
Is there any C++ implementation (source codes) of "optmistic approach to lock-free FIFO queues" algorithm?
Herb Sutter covered just such a queue as part of his Effective Concurency column in Dr. Dobbs Journal.
Writing Lock-Free Code: A Corrected Queue
I want to conclude the answer given by greyfade, which is based on http://www.drdobbs.com/high-performance-computing/212201163 (the last part of the article), the optimized code would be (with some modification to suit my naming and coding convention) :
`
template <typename T> class LFQueue {
private:
struct LFQNode {
LFQNode( T* val ) : value(val), next(nullptr) { }
T* value;
AtomicPtr<LFQNode> next;
char pad[CACHE_LINE_SIZE - sizeof(T*) - sizeof(AtomicPtr<LFQNode>)];
};
char pad0[CACHE_LINE_SIZE];
LFQNode* first; // for one consumer at a time
char pad1[CACHE_LINE_SIZE - sizeof(LFQNode*)];
InterlockedFlag consumerLock; // shared among consumers
char pad2[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
LFQNode* last; // for one producer at a time
char pad3[CACHE_LINE_SIZE - sizeof(LFQNode*)];
InterlockedFlag producerLock; // shared among producers
char pad4[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
public:
LFQueue() {
first = last = new LFQNode( nullptr ); // no more divider
producerLock = consumerLock = false;
}
~LFQueue() {
while( first != nullptr ) {
LFQNode* tmp = first;
first = tmp->next;
delete tmp;
}
}
bool pop( T& result ) {
while( consumerLock.set(true) )
{ } // acquire exclusivity
if( first->next != nullptr ) { // if queue is nonempty
LFQNode* oldFirst = first;
first = first->next;
T* value = first->value; // take it out
first->value = nullptr; // of the Node
consumerLock = false; // release exclusivity
result = *value; // now copy it back
delete value; // and clean up
delete oldFirst; // both allocations
return true; // and report success
}
consumerLock = false; // release exclusivity
return false; // queue was empty
}
bool push( const T& t ) {
LFQNode* tmp = new LFQNode( t ); // do work off to the side
while( producerLock.set(true) )
{ } // acquire exclusivity
last->next = tmp; // A: publish the new item
last = tmp; // B: not "last->next"
producerLock = false; // release exclusivity
return true;
}
};
`
another question is how do you define CACHE_LINE_SIZE? its vary on ever CPUs right?
Here is my implementation of a lock-free FIFO.
Make sure each item of T is a multiple of 64 bytes (the cache line size in the Intel CPUs) to avoid false sharing.
This code compiles with gcc/mingw and should compile with clang. It's optimized for 64-bit, so to get it to run on 32-bit would need some refactoring.
https://github.com/vovoid/vsxu/blob/master/engine/include/vsx_fifo.h
vsx_fifo<my_struct, 512> my_fifo;
Sender:
my_struct my_struct_inst;
... fill it out ...
while (!my_fifo.produce(my_struct_inst)) {}
Receiver:
my_struct my_struct_recv;
while(my_fifo.consume(my_struct_recv))
{
...do stuff...
}
How about this lfqueue
This is cross-platform, unlimited enqueue thread safety queue, have been tested multi deq, multi enq-deq and multi enq. Guarantee memory safe.
For example
int* int_data;
lfqueue_t my_queue;
if (lfqueue_init(&my_queue) == -1)
return -1;
/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
while (lfqueue_enq(&my_queue, int_data) == -1) {
printf("ENQ Full ?\n");
}
/** Wrap This scope in other threads **/
/*Dequeue*/
while ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
printf("DEQ EMPTY ..\n");
}
// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/
lfqueue_destroy(&my_queue);
If you're looking for a good lock free queue implementation both Microsoft Visual Studio 2010 & Intel's Thread Building Blocks contain a good LF queue which is similar to the paper.
Here's a link to the one in VC 2010