[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

c++ static callback method question

Posted on 2011-10-04
8
Medium Priority
?
530 Views
Last Modified: 2012-08-13
I have code used to monitor data received over a network.

I have a static instance of a class which is used to calculate the bitrate and has a static method as follows:

static int DataReceivedCallBack(long bytesReceived, void* userData);

Open in new window


This function is called from inside various dlls whenever data is received.

int MyBandwidthManager::DataReceivedCallBack(long dataLength, void* userData  )
{
     MyBandwidthManager* bwMgr = static_cast<MyBandwidthManager*>(userData);
     bwMgr->UpdateBitrate(dataLength);
     
     return 0;
}

void MyBandwidthManager::UpdateBitrate( long bytesReceived)
{		
		unsigned long timeStampNow =  timeGetTime();
                // blah blah
                // do bitrate calculations
 }

Open in new window


The various dlls in question are used to receive video from different sources, I pass the DataReceivedCallBack into these dlls as a callback function.

The problem I am having is that I see sometimes (using debug messages) that timeStampNow contains the exact same time but the function DataReceivedCallBack has been called by two different dlls.

I thought that the fact that the method was static meant that it could be called only once at any one time??? And not twice at the same time??

To calculate the bite rate correctly I need the timestamp between incoming data to be always incrementing.

Any ideas/help??

Thanks
0
Comment
Question by:Wanting2LearnMan
8 Comments
 
LVL 40

Accepted Solution

by:
evilrix earned 336 total points
ID: 36910703
The fact the function is static has no baring on this. C++ has no concept of threads. A function can be entered by any number of threads at any time unless you use a mutex primitive to prevent this.
0
 
LVL 16

Assisted Solution

by:HooKooDooKu
HooKooDooKu earned 664 total points
ID: 36911021
A static member function is simply a class function that can be called without a class reference.

Typically, when a class member function is called, a hidden 'this' pointer is passed to the class.  That way, when the function attempts to access a member variable, under the hood, the compiler accesses the variable with the hidden 'this' pointer.

But with a static member function, no 'this' pointer is provided.  As such, the static member function is limited to accessing static member variables.

Now the only reason a static member function can access the static member variables is because when a member variable is declared, all instances of the class share the same variable.  Since a static member variable is known to all instances of the class, then even the static member function that has no 'this' pointer can still access the static variables.

As evilrix pointed out, if you want multiple threads or processes to call the same function, yet insure uniqueness of the time stamp, then you would have to utilize a thread synchronization object.  If all the threads accessing your function are in multiple processes (programs), then you could use a CMutex object to only allow one thread to get a timestamp at a time.  If all the threads are in a multithreaded process, then you can use the more efficient CCriticalSection object.

Of course you still have to do more than limit access to the function call to just one thread/process at a time.  timeGetTime returns the time in milliseconds.  With modern GHz speed processes with multiple cores running, thousands of instruction can be executed in one millisecond.  So you would need to modify your function to first only allow one thread/process to execute the code at once, you would also have to add logic that tracks the most recent time value that was returned and make sure the current time being returned is greater than the previous one.

0
 
LVL 16

Assisted Solution

by:HooKooDooKu
HooKooDooKu earned 664 total points
ID: 36911034
Opps, change the text

"Now the only reason a static member function can access the static member variables is because when a member variable is declared, all instances of the class share the same variable."

to

"Now the only reason a static member function can access the static member variables is because when a member variable is declared STATIC, all instances of the class share the same variable."
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:Wanting2LearnMan
ID: 36911094
Thanks guys, good interesting points.

I have added a lock, and I noticed that sometimes the same time was still being returned (due to the speed of the processor and timeGetTime returning milisecs) - so I added a Sleep(1) in for now which should be good enough for my calculations.
 
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 332 total points
ID: 36911121
Also, you are using 'timeGetTime()', which is only 'accurate' up to 1ms (and that's optimistic, you could as well use 'GetTickCount()'), so chances are that the time stamps returned by that API seem identical regarding their values, but in fact are not, because both events occured within the same resolution window.
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 668 total points
ID: 36911220
if you want the function to run exclusively you could add

static CRITICAL_SECTION cs;
static bool once = true;
if (bwMgr == NULL && once == false)
{
    DeleteCriticalSection(&cs);
    return;
}
if (once)
{
   once = false;
   InitializeCriticalSection(&cs);
}
EnterCriticalSection(&cs);
bwMgr->UpdateBitrate(dataLength);
Sleep(1000);
LeaveCriticalSection(&cs);

Open in new window


around the UpdateBitrate call. it would make the UpdateBitRate an exclusively running code, what means that a second thread must wait for the first thread. the Sleep would guarantee that a next timestamp has a different value.

the code above is not quite safe cause the very first call should be not same time with a second call cause the initializing part is not thread-safe.

another approach would be to always add (like adding milliseconds) an incremented number to the timestamp. you can get  the number from a static int initialized to 0. to make that fully thread-safe do the incrementation by a call to InterlockedIncrement though that probably is overkill and a normal ++ increment would do also.

Sara

Sara
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36911234
seems i was a little bit slow with my suggestions ...

Sara
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 668 total points
ID: 36911321
if milliseconds did not prevent from getting the same timestamp you probably better should use the InterlockedIncrement in order to make the incrementing thread-safe.

static LONG volatile uni = 0;
LONG toadd = InterlockedIncrement(&uni);

Open in new window


the 'toadd' would be unique even if the threads would run same time.

Sara
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question