Distributed Objects, Threading, Objective-C - objective-c

I have a working server/client app using Distributed Objects in objective-c. What I am struggling with right now is making the app multi-threaded. So that more users can access the server at the same time.
Here is main function for the server. This is where I create the nsconnection object.
From my understanding, the way I should approach this is when a user tries to access the server, a new thread should be allocated for that particular call. Should the [conn runInNewThread] takes care of this ?
Any thoughts is appreciated...
Here is the code for the server.
int main (void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Transactions *trans = [Transactions new];
NSConnection *conn = [NSConnection defaultConnection];
[conn setRootObject: trans];
[conn runInNewThread];
if (![conn registerName:#"holycow"])
{
NSLog (#"Failed registering holycow.");
exit (1);
}
NSLog (#"waiting for connections...");
[[NSRunLoop currentRunLoop] run];
[pool release];
return 0;
}

In order to respond to client messages, the responding server object
must be set as the ’root object’ of an instance of the NSConnection
class, and this NSConnection must be registered with the network by
name.
So in case of Distributed object, single server object can handle multiple clients. or you can create more server object and divide your clients.

#Parag Bafna was right in his answer when I ran a test. However, I used a special kind of architecture in the server that may have aided in this. Take for instance a command that takes a long time to run on the server daemon. This can hang a server up a bit and make it much slower for connections to be processed. Here's my solution.
Have the client call an asynchronous class method using the oneway property. Let's call this runProcess.
Make runProcess do a popen() on the task and keep the PID as a global variable.
Then, make it use performSelectorInBackground to run a synchronous class method called readProcess in the background.
In readProcess, I use while(fgets(buff, sizeof(buff), ghPID)!=NULL) to read the previously established popen() output (note the global variable, ghPID) and append the latest line read into a global variable of recent lines read. This method runs as a background task, and the client has already disconnected from runProcess.
Now have the client connect to a synchronous class method called getProcessData. This should then take the global variable of recent lines read and return it back. Since that doesn't take very long to do, the client disconnects from that class method pretty quickly.
The client can then poll that data until it knows it's done. To aid with that, you can create a synchronous method called isProcessRunning that can check on a global boolean variable on the server daemon called gbRunning and return true/false. Of course, though, it will be up to you to flip that variable in the server daemon true/false in the various class methods when the server is busy running a popen() task.
By doing it this way, your server daemon can respond to concurrent requests much faster.
An additional tip would be to use a kill file or other mechanism (shared memory? SIGHUP?) so that if you're in a while loop and you want that process to stop, you can just drop a kill file somewhere in /tmp for instance and the process will use pclose to kill it and then erase the kill file. I also do this before starting a process if I want to ensure only one particular process runs at a time from that server daemon.

Related

How do I call some blocking method with a timeout in Obj-C?

Is there a standard nice way to call a blocking method with a timeout in Objective C? I want to be able to do:
// call [something blockingMethod];
// if it hasn't come back within 2 seconds, forget it
Thanks.
It is not possible to interrupt a function that is not designed to be interrupted. Doing so would generally cause data corruption and resource leaks.
The standard way to achieve what you're describing is to redesign blockingMethod so that it accepts a timeout or other cancelation mechanism.
If that's not possible, and it is required that you timeout blockingMethod, the standard approach is to fork a child process to run blockingMethod, and kill it (usually by sending SIGTERM) if it doesn't finish by the timeout. This is somewhat complex to implement in ObjC, and you'll need to also implement a mechanism to send the results back to the parent process. Since the operating system manages resources (memory, file handles, etc) at the process level, the only way to forcibly interrupt a function is to create a separate process for it. This still can lead to data corruption depending on what blockingMethod does, but it will work for a much larger set of problems.
Note that it's not generally possible to fork a process from non-Apple code on iOS, so this can't be done there.
As an example of what I mean by "data corruption," consider some simple code like:
[self.cache lock];
[self.cache removeObject: object];
[self.cache decrementCountOfObjects];
[self.cache unlock];
Now imagine that the process were forcibly terminated in the middle of this operation. What should happen? How does the cache get unlocked? How are the cache contents and the count reconciled? It's even possible that the object would be in the middle of being copied; then what? How would the system automatically deal with all of these issues unless blockingMethod were written with cancelation in mind?
How about using a semaphore? This can be locked across threads and then you can do something like
dispatch_semaphore_t s = dispatch_semaphore_create ( 0 );
// In a different thread or on some queue,
// fire up some process, when done signal
// the semaphore with
[ fire up thread ... some task, when done
dispatch_semaphore_signal( s );
... ]
// This waits 2 seconds for the semaphore
if ( dispatch_semaphore_wait( s, 2 ) )
{
// ... it hasn't come back after 2 seconds so 'forget it'
}
else
{
// ... you now have the semaphore within 2 seconds so 'do it'
}
// This waits forever, just for reference
dispatch_semaphore_wait( s, DISPATCH_TIME_FOREVER );

Understanding the Objective-C event loop

How can I log every message sent in a single iteration of the Objective-C event loop?
I want to further my understanding of the Objective-C runtime and thought this would be a good start.
These functions will cause all messages to be logged to a file in /tmp, based on the PID of the process. Good on simulator, but not on an iDevice.
// Start logging all messages
instrumentObjcMessageSends(YES);
// Stop logging all messages
instrumentObjcMessageSends(NO);
The CFRunLoopObserver opaque type should do exactly what you want. It is
a general means to receive callbacks at different points within a running run loop.
Use the activity argument to its creation function to specify when you want your observer serviced. For your case, this will probably be either kCFRunLoopEntry or kCFRunLoopExit.
You can get the CFRunLoopRef from the current NSRunLoop, [[NSRunLoop currentRunLoop] getCFRunLoop], or by using CFRunLoopGetCurrent().

Replacing a call to sleep when waiting on an NSStream response

I made an application which uses NSStream to etablish a connection to a telnet server.
When the connection is made, I send a first command. Then I use sleep(1); to make my application wait. Then the second command is sent.
The problem is that the entire GUI is stuck during the sleep(). I know that it's not the "perfect" way to make a "pause" and I'd like to learn how to this properly. I heard good things about NSTimer but I'd like to have a concrete and "easy" way of using it, to simply replace my poor use of sleep().
You should be able to register some kind of callback with whatever procedure you're using to establish the connection. Just let your code wait for that callback without doing anything at all.
In this case, using NSStream, you need to schedule the stream on the run loop:
[stream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
The run loop is the construct that processes events for your application. When you use sleep(), it is stopped, and your GUI can't do anything. By adding the stream as input to the run loop, you allow them both to continue to work.
You also must set a delegate object ([stream setDelegate:self];, e.g.) which will recieve notifications when the stream has something to report. That delegate must implement stream:handleEvent:, which will be called with a reference to the stream and a code indicating what happened.

Asynchronous NSUrlConnection not on main runloop

I am creating a set of classes which interface with a web service. At the core of this, the data is retrieved from the service using an asynchronous NSUrlConnection. In my mind, it is important that it is asynchronous, as a client of these web service interfaces has to have the ability to cancel a request that is in progress (i.e. cancel an NSUrlConnection).
The web service calls return JSON data, potentially lots of it, and this is parsed and the classes I am creating will create proper data structures out of them. Depending on which web service method is called, the request can end up being expensive - too expensive to run on the main thread, so I would like to either add the option of running the service requests asynchronously, or not giving the option, and forcing asynchronous calls.
Async calls are all well and good, but I am having problems starting an NSUrlConnection asynchronously on a runloop that isn't the main one. The problem I'm describing seems to be fairly well documented: I am led to believe the delegate of the NSUrlConnection is not called because the runloop that launches the connection has terminated, and therefore the calls back to the delegate cannot be scheduled on its runloop.
What is the best way to go about solving this issue?
I have tried using:
while (!self.isRequestComplete && !self.isRequestCancelled)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
It seems to work ok from the basic trial I have done, except if the runloop that this is being executed on is actually the main runloop, for which I have had a few crashes...
Would an option be to offer asynchronous calls to clients, and then use the above method if the option is utilised? Is there a better way of achieving what I am trying to do?
What I am aiming to achieve is for a package of classes that allow interfacing with my specific web service, where the clients of my code do not need to worry about whether their own delegates (which my classes hold references to) will be called on different threads. I want them to be called on the exact same runloop that they called my code on - basically, exactly how NSUrlConnection operates!
Thanks in advance!
Nick
I think you may have "gone up the wrong creek" so to speak. Generally speaking you don't need to worry about run loops unless you are doing something rather odd. It sounds like you need to do some reading on multi-threading, particularly Grand Central Dispatch.

Background network calls - iOS

I need to implement posting some data to a web server in the background. Just to clarify, by "in the background", I don't mean the normal way of showing a spinning icon and posting data to a web service using something like an AsyncTask or ASIHTTPRequest's [request startAsynchronous] method. I need to maintain a queue of data that a Thread can asychronously start processing and posting to a Web service while the user is working in the application.
I'm looking for some help on designing a queue like that, especially in some edge cases like User receiving a call, logging out of the application while the the post is happening, user leaving the application to goto a different one while a post is happening and the like. How would you handle these cases? Is there any source code you can recommend that does this?
Thanks,
Teja.
I've started using NSOperationQueue in my own work lately, for controlling background network requests. NSOperation deals with most of the boilerplate code necessary for asynchronously running tasks (such as network operations) on threads in the background (or foreground, if necessary for UI updates).
It also allows dependencies across queues; for example, I use two queues in my application:
The first schedules image downloads, at a max concurrency of 2 at a time, in the background. Each image download has a corresponding completion handler (as an NSBlockOperation) that is dependent on the image download completing. These operations sit on the [NSOperationQueue mainQueue], which operates on the main thread, allowing them to update UI (specifically, the corresponding UIImageView).
Note that NSOperation and NSOperationQueue are not for network requests only, but any operation that can be divided into atomic tasks and scheduled concurrently.
Here are Apple's intro docs on the topic.
Having implemented something similar myself, I would recommend using a service and not a thread to do network calls. That way even if your activity gets killed you're sure your network calls will be executed.
Then to implement the queue i suggest you take a look into IntentService (http://developer.android.com/reference/android/app/IntentService.html)
from the docs:
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work.
This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it,
extend IntentService and implement onHandleIntent(Intent).
IntentService will receive the Intents, launch a worker thread, and
stop the service as appropriate.
All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop),
but only one request will be processed at a time.
If your application is simple enough you can use sendBroadCast() to share info and notifications between your activity and the IntentService
Create a singleton that encapsulate a thread :
In the initialisation of your object :
[NSThread detachNewThreadSelector:#selector(mainPosterThread) toTarget:self withObject:nil];
- (void)mainDownloaderThread
{
if( [NSThread respondsToSelector:#selector(setThreadPriority:)] )
{
[NSThread setThreadPriority:0.1];
}
NSString *urlToDownload = nil;
while(shouldRun)
{
// Take next data to post in a queue (lastObject of a NSArray for example)
if( nextDataToPost )
{
// Post
}
else
{
// Sleep for some time.
}
}
}
You can also have methods for stopping / starting the thread while the app go background / foreground on a multitask supported device. If no multitasking supported, save the post data in the queue at stop time (if not too long) and restore them at start. The biggest chalenge is to manage be able to cancel the current upload while app will ends.
This is an issue which I've been perfecting in every new application I write. Basically I wanted network functionality which is asynchronous and which was written by me using native functionality. I'd be happy to show you some of this code if you're interested.
First of all, I suggest that you make all network calls on the main thread asynchronously rather than synchronously, using a delegate. This way serialization/synchronization/concurrency is not an issue. And since classes are network delegates, I'd just set up one class to where a new connection has a new delegate instance.
[[NSURLConnection alloc] initWithRequest:request delegate:del] autorelease];
e.g.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data