Problem Description
I have a function StdString ShowLockScreen() in this function I call activateViewController function which shows some UI where user must enter PIN, just after calling activateViewController function I want to lock all processes until user will enter his PIN and press OK button on opened UI. Below you can see code which I try
Source code in iOS
StdString ShowLockScreen()
{
// Create a lock.
NSLock* theLock = [[NSLock alloc] init];
// Create a UI in which user must enter his PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
// Set delegate.
controller.delegate = m_Context;
// !!! Here I show a UI and just after that I lock my lock in order code stop executing there.
[controller activateViewController:nil];
#synchronized(theLock) {
[theLock lock];
}
NSLog(#"User in UI unlock the lock");
}
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing. But it doesn't work in my case.
Source code in Android
I have write similar application in Android and here is code. I want to write same in iOS but I can;t find solution
Intent intent = new Intent(mCtx, SoftPinActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedObject lock = new SharedObject("");
int lockId = SharedObject.acquireLockId(lock);
Logger.i(TAG, "lockId = " + lockId);
intent.putExtra(SharedObject.LOCK_ID, lockId);
intent.putExtra(SoftPinActivity.UI_ID, style);
synchronized (lock) {
mCtx.startActivity(intent);
try {
Logger.i(TAG, "lock.wait()...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Logger.i(TAG, "InterruptedException");
}
}
Logger.i(TAG, "lock.wait()...done");
SharedObject.releaseLockId(lockId);
String pin = lock.object();
Researches
I think I must use
NSCondition* condLock = [[NSCondition alloc] init];
[condLock wait];
and
[condLock signal];
but how to use this in my code ?
Answer to problem
You can lock threads using NSLock, but in your situation, this doesn't seem to be applicable. The reason being is that locking is primarily used to provide thread safety when data is accessed from multiple threads. What you're asking for is a domain level lock, which prevents the user from using the application unless they've typed in their PIN. These two concepts share the word "lock", but they're entirely different in their implementation. If you were to use NSLock and its related counterparts, you're forcing your implementation into separate threads purely to block user interaction, and risk complicating your project and pains in debugging (deadlocks much?).
Suggested solution
As the concept is a domain level locking mechanism, I suggest we keep it this way for its implementation. If you want it to be analogous to Android, then you'd need to create your own concept of a 'SharedObject' that everything else queries. If this object were to say "The user hasn't unlocked the application", then nothing will process. This keeps you away from manually managing threads, and frees threads up for when you really need them most (asynchronous processing for example).
To implement this object, lets call it a UserContext, which is available as a singleton. How to implement this sharedInstance can be seen here.
Once you have that, then you can add various properties to it that are global throughout the application (and by the suggestion of the name, has all global properties that belong to a particular user). One of these properties is whether the user has the app locked or not:
[[UserContext sharedInstance] isLocked] // Returns BOOL
Using this throughout your application, you can then control (at the domain concept level), whether a method can compute something or not (naturally, you'll need to make UserContext thread safe, as it could be queried anywhere at any time). It would make it clear to the developer reading the code, that a certain method can not do anything unless the user has unlocked the app. To stop
Side notes
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing.
Do not, under any circumstances, lock the UI thread. In a published app, the watchdog will kill your app, and it will effectively crash.
ViTo, as much I concerned with the NSLock, we use it in the case of multi-threading in which we lock a particular thread and force that upto that not unlock, none other thread become active or to do his required task.
So, may be what we can do that first of all we start all of your processes in the terms of thread and at that point when you try to open your UI we call 'lock' and when user pressed the button after inputting the text-box then we call 'unlock'.
But, for this we've to sure that this thread has high priority.
That's what I'm thinking right now, but really try this with my sample code and will update you accordingly.
Check that part of code:
+(void)aMethod:(id)param{
int x;
for(x=0;x<50;++x)
{enter code here
[lock lock];
printf("Object Thread says x is %i\n",x);
usleep(1);
[lock unlock];
}
}
- (void)viewDidLoad
{
int x;
lock = [[NSLock alloc] init];
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MViewController class] withObject:nil];
for(x=0;x<50;++x)
{
[lock lock];
printf("Main thread says x is %i\n",x);
usleep(10000);
printf("Main thread lets go %i\n",x);
[lock unlock];
usleep(100);
}
printf("Now getting the process");
[super viewDidLoad];
}
Check the log you'll get what you want.
Hope, it's what you need. For any concern, shout-over me.
Okay I found solution to this issue, below you can see implemented function and line by line description.
StdString ShowLockScreen()
{
// Create NSCondition lock object.
NSCondition* conditionLock = [[NSCondition alloc] init];
// Here I create my UI which must ask user to enter PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
controller.delegate = m_Context;
// Here I lock the thread but not main thread (this is very important) I start
// ShowLockScreen function in new thread and lock it.
[conditionLock lock];
dispatch_sync(dispatch_get_main_queue(), ^{
// I call function which shows my UI in main thread as UI can be shown
// only in MAIN THREAD. (This is important too.)
[controller ShowLockController:conditionLock];
});
// Then I set lock to wait, how you can see I pass conditionLock as an
// argument to ShowLockController function in that function when user
// enter his PIN and press okay button I call [conditionLock signal];
// and my code code here after wait and continue executing.
[conditionLock wait];
NSLog(#"Come here then I call [conditionLock signal]!!!")
}
Related
Introduction
I am new to multithreading. I have an created a GUI application in c++ on windows 10 using wxWidgets. A worker thread communicates in the background via sockets and appends events to some event handlers from the main thread (GUI); I have two available protocols for the communication, and I allow the user to choose among those at the beginning (before instantiating the thread). To append events, I have a few shared pointers on the event handlers; a bit like in this tutorial, where it keeps a pointer of the m_parent. To communicate with the working thread, I created a queue using a mutex and semaphore, also like in the tutorial. For now, everything works.
Now, I want to let the user change the protocol while the application runs. I have thus a menu with a related button. This button calls the following function (create_app()) that deletes the top window and the communication thread and recreates everything. That is where I have problems.
bool cApp::create_app() {
wxWindow* main_window = GetTopWindow();
// If there is already a window, delete everything before creation
if(main_window) {
//thread_communication->Wait(); // Should I wait for the thread to finish? I shouldn't
if (thread_communication->Delete() != wxTHREAD_NO_ERROR) { // Should I delete it since it should be destroyed when Entry is finished
std::cerr << "DELETE IMPOSSIBLE!" << std::endl;
return false;
}
if (main_window->Destroy() != wxTHREAD_NO_ERROR) { // Here I can't delete the window
std::cerr << "DELETE WINDOW IMPOSSIBLE!" << std::endl; // prints
return false;
}
SetTopWindow(NULL);
}
// Create everything
m_frame1 = new MainFrame(*this);
SetTopWindow(m_frame1);
m_frame1->Show();
std::vector<std::shared_ptr<wxEvtHandler>> evt_handlers;
m_frame1->get_handlers(evt_handlers);
// Construct the working thread with the evt handlers and the queue from the main window
thread_communication = std::unique_ptr<ThreadCom>(new ThreadCom(evt_handlers, m_frame1->get_queue());
wxThreadError err = thread_communication->Create();
...
err = thread_communication->Run();
...
return true;
}
bool cApp::OnInit() {
return create_app();
}
When the user click the related button, it calls this create_app function but before sends a task via the queue to the working thread with the highest priority (meaning it will be the next task achieved by it); afterwards, in the working thread, it exits after poping the task the while loop in Entry. Thus, the working thread should terminate there.
Problem
I have problem when deleting the thread and the application. I have memory leaks since, I guess, they share common material (pointers).
When I try to use Wait, I have first a assert !IsDetached. That is because I cannot wait for a detached thread. If I continue, the programm crashes (Access violation reading location) during the thread->Delete() call.
If I don't use Wait, the thread->Delete() call works fine. Afterwards, the program crashes at main_window->Destroy(); the return code is not ok thus it prints "DELETE WINDOW IMPOSSIBLE" with an Unhandled exception thrown: read access violation message.
So, how should I proceed? Should I implement destructors in the classes? How can I delete the thread and the app safely?
Thanks in advance for your help.
In my current project I need to perform some calculations when a specific button is pressed, and while I perform these calculations, I want to show a Gtk::MessageDialog that simply states that calculations are being performed. So, I initialize the MessageDialog like this (for the moment just ignore that I actually don't need the pointer here):
Gtk::MessageDialog *waitdialog;
Gtk::MessageDialog dia("Processing", false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE, true);
dia.set_title("Wait.");
dia.set_transient_for(*(Gtk::Window *)this);
waitdialog = &dia;
Next I want to start a separate thread with the dialog:
std::thread dialog_thread(wait_dialog,waitdialog);
The wait_dialog method is defined as follows:
void wait_dialog(Gtk::MessageDialog *dialog){
dialog->run();
}
The problem now is, that even though the main window is darkened (because of set_transient_for), the message dialog is not visible. However, when I don't start a seperate thread, but just call waitdialog->run() instead, this will show the dialog properly (but will result in a loop).
So, the question is: why does the workaround with the separate thread not work? I can't make any sense of that :-(
GUI components are required to stay in the GUI loop. Your long running calculations belong in the thread. The calculation thread then signals back to the GUI thread to close the modal dialog. Also, you should use glib threads instead of std::threads. Here's how I would structure program:
// in header, member var dispatcher used to signal GUI thread
// and our member var thread
Glib::Dispatcher m_signalDone;
Glib::Thread* m_someThread;
...
// in constructor, hook up dispatcher event
m_signalDone.connect(sigc::mem_fun(this, &MyClass::OnDone));
...
// later when ready to kick off thread...
// show dialog or progess bar or something and kick off thread...
m_someThread = Glib::Thread::create(sigc::mem_fun(*this, &MyClass::CalcMethod), true);
...
void MyClass::CalcMethod()
{
// do your long running stuff...
// when done signal completion back to GUI
m_signalDone.emit();
}
...
void MyClass::OnDone()
{
// clean up dialog or progress bar or whatever
// kill thread
m_currentBackUpThread->join();
m_currentBackUpThread = NULL;
}
We are building a content editor that brings up a "cocos Player" in an NSWindow for test purposes. The user can test some content and then close the window.
So I need to be able to shutdown cocos and re-start within the same app.
Everything is working if I use the CC_MAC_USE_DISPLAY_LINK_THREAD threading model. I had to make a fix in CCDirectorMac to get this working. In CCDirectorMac | stopAnimation I had to set the _runningThread to nil since it is not set to nil by the #if and #elif when using CC_MAC_USE_DISPLAY_LINK_THREAD.
Anyway so now I am able to "end" a director and then re-start it later with no issues.
My question though is this: If I am building an AppKit editor with occasional use of cocos2D whould my threading model really be CC_MAC_USE_MAIN_THREAD as is suggested in the documentation?
When I do use CC_MAC_USE_MAIN_THREAD I get a HANG in in stopAnimation on the line:
CVDisplayLinkStop(displayLink);
I think the main thread would be fine and would avoid threading issues for our tool. Performance is not a concern. I can't find any sample code that shuts down and restarts cocos2d in an NSWindow ... so my assumption here is that I am in untested waters (or little tested waters).
My steps to shutdown/restart are:
Call [[CCDirector sharedDirector] end]
This calls stopAnimation
Then re-initialize cocos2d the same way I did originally
Any advice on threading models for a Mac desktop app ... and why CVDisplayLinkStop hangs would be greatly appreciated.
Thanks in advance.
Ok, I figured it out after reading this post and its answers on the Apple mailing list: http://lists.apple.com/archives/quartz-dev/2006/Oct/msg00056.html
When using CC_MAC_USE_MAIN_THREAD, the display link thread uses performSelector:onThread:waitUntilDone: to run drawScene: on the main thread. It passes YES for the waitUntilDone: parameter, so the display link thread blocks until the main thread can process the drawScene: call.
Here's the relevant fragment of the cocos2d code. MyDisplayLinkCallback is called on the display link thread.
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime];
return result;
}
- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
{
#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_DISPLAY_LINK_THREAD)
...
#else
// Display link thread blocks here:
[self performSelector:#selector(drawScene) onThread:_runningThread withObject:nil waitUntilDone:YES];
#endif
return kCVReturnSuccess;
}
The problem appears when the main thread tries to run CVDisplayLinkStop() which blocks until the display link callback in the display link thread finishes. Since the callback is at the same time waiting for the main thread to process its drawScene: call, both threads become deadlocked.
- (void) stopAnimation
{
...
if( displayLink ) {
// Main thread blocks here:
CVDisplayLinkStop(displayLink);
...
}
So, now for my workaround. I added a line to run the main thread's runloop in order to force the drawScene: call to be executed, which unblocks the display link thread. That way, when you call CVDisplayLinkStop() you're safe. Here's my addition (CCDirectorMac.m line 473 in cocos2d 2.1 release):
- (void) stopAnimation
{
...
if( displayLink ) {
#if (CC_DIRECTOR_MAC_THREAD != CC_MAC_USE_DISPLAY_LINK_THREAD)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
#endif
CVDisplayLinkStop(displayLink);
...
}
I'm not sure this is the right thing to do, there's probably a better way to deal with this, but this workaround is good enough for me at the moment.
Thanks for this post, it helped me figure out how to solve the same deadlock, in a non-cocos2d app, by processing the display link callback on a separate thread, never on the main thread.
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void *userInfo)
{
static dispatch_queue_t sDisplayQueue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sDisplayQueue = dispatch_queue_create("com.company.app.displayLink", NULL);
});
dispatch_sync(sDisplayQueue, ^{
<stuff>
});
return kCVReturnSuccess;
}
I using Indy with C++ Builder XE3. It's perfect system but i have some problems. IdTCPServer works really good but when i have some connections on him and i want to stop server then my application freezed. I try to tell how i do it step by step:
1) Starting application (and server listening)
2) wait for new connections (or simulate it, no difference)
3) when we have 10-15 connections - then try to stop server listening.
4) when code came to IdTCPServer1->Active = false - application will be frozen
i made little video. Maybe it explain situation much better. http://www.youtube.com/watch?v=BNgTxYbLx8g
And here my code:
OnConnect:
EnterCriticalSection(&CritLock);
++ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
OnDisconnect:
EnterCriticalSection(&CritLock);
--ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
StopServer Code:
void TForm1::StopServer()
{
TList *list = IdTCPServer1->Contexts->LockList();
try
{
for(int i = 0; i < list->Count; ++i)
{
TIdContext *AContext = reinterpret_cast<TIdContext*>(list->Items[i]);
try
{
if (AContext->Connection->Connected())
{
AContext->Connection->IOHandler->InputBuffer->Clear();
AContext->Connection->IOHandler->WriteBufferCancel();
AContext->Connection->IOHandler->WriteBufferClear();
AContext->Connection->IOHandler->WriteBufferClose();
AContext->Connection->IOHandler->CloseGracefully();
AContext->Connection->Disconnect();
}
}
catch (const Exception &e)
{
}
}
}
__finally
{
IdTCPServer1->Contexts->UnlockList();
}
IdTCPServer1->Contexts->Clear();
//IdTCPServer1->StopListening();
IdTCPServer1->Active = false;
}
Thanks for advise!
You need to get rid of all your StopServer() code except for the very last line. When TIdTCPServer is deactivated, it performs all necessary cleanups for you. DO NOT DO IT YOURSELF (especially since you are doing it wrong anyway).
void TForm1::StopServer()
{
IdTCPServer1->Active = false;
}
Now, with just that code, if your app is still freezing, then that means you are deadlocking the main thread. That happens if you call StopServer() in the context of the main thread and one of two things are happening in your server code:
one of your TIdTCPServer event handlers performs a synchronized operation to the main thread (either via TIdSync or TThread::Synchronize()).
one of your TIdTCPServer event handlers swallows Indy exceptions and does not allow TIdTCPServer to terminate one or more client threads correctly when needed.
Internally, the TIdTCPServer::Active property setter closes all active sockets and waits for their respective threads to fully terminate, blocking the calling thread until the property setter exits. If yoou are deactivating the server in the main thread and one of the server threads performs a sync that the main thread cannot process, or otherwise does not terminate correctly when it should be, that will block the server deactivation from exiting and thus deadlock the main thread.
So make sure that:
you are not performing sync operations to the main thread while the server is being deactivated by the main thread. If you must sync, then deactivate the server in a worker thread instead so the main thread is not blocked anymore.
your event handlers are not swallowing any Indy EIdException-derived exceptions in try/catch blocks. If you catch such an exception, re-throw it when you are finshed using it. Let TIdTCPServer handle any Indy exceptions so it can perform internal cleanups as needed.
Lastly, on a side note, you do not need to keep track of connections manually. TIdTCPServer already does that for you in the Contexts property. If you need to know how many clients are currently connected at any moment, simply Lock() the Contexts list, read its Count property (or do anything else you need to do with the clients), and then Unlock() the list.
Greetings, everyone!
I have a class (say, "Switcher" ) that executes some very-very long operation and notifies its listener, that operation is complete. The operation is long, and I isolate actual switching into separate thread:
class Switcher
{
public:
// this is what other users call:
void StartSwitching()
{
// another switch is initiated, I must terminate previous switching operation:
if ( m_Thread != NULL )
{
if ( WaitForThread(m_Thread, 3000) != OK )
{
TerminateThread(m_Thread);
}
}
// start new switching thread:
m_Thread = StartNewThread( ThreadProc );
}
// this is a thread procedure:
static void ThreadProc()
{
DoActualSwitching();
NotifyListener();
}
private:
Thread m_Thread;
};
The logic is rather simple - if user initiates new switching before the previous one is complete, I terminate previous switching (don't care of what happens inside "DoActualSwitching()") and start the new one. The problem is that sometimes, when terminating thread, I loose the "NotifyListener()" call.
I would like to introduce some improvements to ensure, that NotifyListener() is called every time, even if thread is terminated. Is there any pattern to do this? I can only think of another thread, that infinitely waits for the switcher and if the switcher is done (correctly or by termination), it can emit notification. But introducing another thread seems an overplay for me. Can you think of any other solution (p.s. the platform is win32)?
Thank you!
First, you should never call TerminateThread. You cannot know which operation is terminated when calling TerminateThread and so that could lead to memory leaks/resource leaks/state corruption.
To get your thread to be interruptable/cancelable, you supply a 'cancel' state, which is checked by the thread itself. Then your notify end will always work.
TerminateThread() here whacks the thread, and if it was inside DoActualSwitching(), that's where it'll die, and NotifyListener() will not be called on that thread. This is what TerminateThread() does, and there is no way to make it behave differently.
What you are looking for is a bit more graceful way to terminate the thread. Without more info about your application it's difficult to suggest an optimal approach, but if you can edit DoActualSwitching(), then I'd add
if (WAIT_OBJECT_0 == WaitForSingleObject(m_ExitThreadEvent, 0))
break;
into the loop there, and call SetEvent(m_ExitThreadEvent) instead of TerminateThread(). Of course you'll need to create the event and add the handle to the class. If your model suggest that there is only one switching thread at a time, I'd use autoreset event here, otherwise some more code is needed.
Good luck!