In my app I'm doing some audio processing.
In the for loop of the audio buffer, there is a NSMutable array. The loop is called a huge number of time every second (depending on the buffer size).
As an example :
#autoreleasepool
{
for ( int i = 0; i < tempBuffer.mDataByteSize / 2; ++i )
{
if ( samples[i] > trig)
{
[self.k_Array addObject:[NSNumber numberWithInt:k]];
// other stuff
}
}
}
Then, every second, I'm calling a function for other processing.
- (void)realtimeUpdate:(NSTimer*)theTimer
{
// Create a copy of the array
NSMutableArray *k_ArrayCopy = [NSMutableArray arrayWithArray:k_Array]; // CRASH with EXC_BAD_ACCESS code 1 error
//do some stuff with k_ArrayCopy
}
I sometime receive an EXC_BAD_ACCESS error because, I think, a locking problem of the array.
I spent a lot of time trying to get information on queues, locking, working copies, etc... but I'm lost on this specific case.
My questions :
do I have to use atomic or nonatomic for k_array ?
do I have to use a dispatch_sync function ? If so, where exactly ?
should the realtimeUpdate function be called on background ?
Thanks in advance !
Use dispatch queue that will solve problem
//create queue instance variable
dispatch_queue_t q = dispatch_queue_create("com.safearrayaccess.samplequeue", NULL);
//1.
#autoreleasepool
{
for ( int i = 0; i < tempBuffer.mDataByteSize / 2; ++i )
{
if ( samples[i] > trig)
{
dispatch_async(q, ^{
//queue block
[self.k_Array addObject:[NSNumber numberWithInt:k]];
});
// other stuff NOTE: if its operation on array do it in queue block only
}
}
}
//2.
- (void)realtimeUpdate:(NSTimer*)theTimer
{
// Create a copy of the array
__block NSMutableArray *k_ArrayCopy;//when you use any variable inside block add __block before it
dispatch_async(q, ^{
//queue block
k_ArrayCopy = [NSMutableArray arrayWithArray:k_Array];
});
//do some stuff with k_ArrayCopy
}
Now your add and read array operation are on same queue and it will not conflict..
For more details in using dispatch queue go through apples Grand Central Dispatch doc
Other way of doing this is use NSConditonLock
Related
On an iPad how many parallel operations can start to get maximum performance? in each run a query operation , calculations , etc ...
It depends on the iPad model (CPU)?
int count = [objects count];
if (count > 0)
{
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < count; i++)
{
dispatch_group_async(group, queue, ^{
for (int j = i + 1; j < count; j++)
{
dispatch_group_async(group, queue, ^{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
});
}
});
}
dispatch_group_notify(group, queue, ^{
/** END OF ALL OPERATIONS */
};
}
This is basically a UX question. Depends on the needs of the end user.
Does he really need all those computations started and finished quickly ?
Can you delay some or most of them ?
It's good practice to inform the user with a progress of each computation (a progress bar) and notify him upon completion.
Let him choose which to start / stop / pause (this is a very important feature).
If all the tasks are local - CPU intensive, and not related to network fetching of resources, then it depends on each CPU device - how many threads can it run in parallel.
I want to get the number of threads which are 'alive' in my iOS application.
Can I use threadDictionary in the NSThread class? Or can I use mach/thread_info.h?
Michael Dautermann already answered the question, but this is an example to get threads count using Mach API.
Note that its work only on simulator (tested with iOS 6.1), running it on device will fail because task_for_pid return KERN_FAILURE.
/**
* #return -1 on error, else the number of threads for the current process
*/
static int getThreadsCount()
{
thread_array_t threadList;
mach_msg_type_number_t threadCount;
task_t task;
kern_return_t kernReturn = task_for_pid(mach_task_self(), getpid(), &task);
if (kernReturn != KERN_SUCCESS) {
return -1;
}
kernReturn = task_threads(task, &threadList, &threadCount);
if (kernReturn != KERN_SUCCESS) {
return -1;
}
vm_deallocate (mach_task_self(), (vm_address_t)threadList, threadCount * sizeof(thread_act_t));
return threadCount;
}
This one works on the device as well:
#include <pthread.h>
#include <mach/mach.h>
// ...
thread_act_array_t threads;
mach_msg_type_number_t thread_count = 0;
const task_t this_task = mach_task_self();
const thread_t this_thread = mach_thread_self();
// 1. Get a list of all threads (with count):
kern_return_t kr = task_threads(this_task, &threads, &thread_count);
if (kr != KERN_SUCCESS) {
printf("error getting threads: %s", mach_error_string(kr));
return NO;
}
mach_port_deallocate(this_task, this_thread);
vm_deallocate(this_task, (vm_address_t)threads, sizeof(thread_t) * thread_count);
"threadDictionary" is information about a specific NSThread. It's not the total number of threads.
If you want to keep track of "NSThread" objects you've created, you'll probably need to create your own NSMutableArray and add new NSThread objects to it and make certain the objects are valid and correct (i.e. threads are executing, threads are finished or cancelled, etc.) each time you want to do a count of your NSThreads.
This likely still would not give you exactly what you want because NSThread isn't the same thing as threads created and/or references via Grand Central Dispatch (GCD) or other kinds of threads (e.g. pthreads).
I have the following code in a loop (it gets called every 1/4 second).
(I have removed the rest of the code to narrow the problem down to the following).
dispatch_async(self.audioQueue, ^{
AudioBufferList *aacBufferList;
aacBufferList = malloc(sizeof(AudioBufferList));
aacBufferList->mNumberBuffers = 1;
aacBufferList->mBuffers[0].mNumberChannels = aacStreamFormat.mChannelsPerFrame;
aacBufferList->mBuffers[0].mDataByteSize = maxOutputPacketSize;
aacBufferList->mBuffers[0].mData = (void *)(calloc(maxOutputPacketSize, 1));
// Other code was here. As stated above, I have removed it to isolate the problem to the allocating and freeing of memory for the AudioBufferList
freeABL(aacBufferList);
}
And the freeABL function:
void freeABL(AudioBufferList *abl)
{
for (int i = 0; i < abl->mNumberBuffers; i++)
{
free(abl->mBuffers[i].mData);
abl->mBuffers[i].mData = NULL;
}
free(abl);
abl = NULL;
}
The problem I have, is every time this loops the memory consumption of my app increased, until I receive a memory warning.
I used Eclispse Indigo + CDT 8.0.2 + cygwin to develope a multi-thread systerm, the code is below:
pthread_mutex_t mutexCmd = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t signalCmd = PTHREAD_COND_INITIALIZER;
void * Func(void * arg)
{
int iStatus;
while (1)
{
int a = 1;
pthread_cleanup_push(pthread_mutex_unlock, &mutexCmd);
pthread_mutex_lock(&mutexCmd);
iStatus = pthread_cond_wait(&signalCmd, &mutexCmd);
if (iStatus) {
err_abort(iStatus, "signalCmd status error");
}
if(arg->Cmd != navi_Go) //Just a command tag;
{
pthread_mutex_unlock(&(pNaviCtrl->mutexCmd));
continue;
}
//do some work
//.....
pthread_mutex_unlock(&mutexCmd);
pthread_cleanup_pop(1);
}
//pthread_detach(pthread_self());
return NULL;
}
int main()
{
int iStatus = 0;
pthread = tid;
iStatus = pthread_create(&tid;NULL, Func, NULL);
if(iStatus)
{
err_abort(iStatus, "Start pthread error");
}
// do some work
...
//Cancel thread
void * retval;
iStatus = pthread_cancel(tid)
iStatus = pthread_join(tid; &retval);
if(iStatus){
err_abort(iStatus,"Stop thread error");
}
return iStatus;
}
where program run, it stop at "iStatus = pthread_join(tid1; &retval);" couldn't go forward anymore, I think the thread could be happed to deadlock, but can't find the reason. I supposed after call pthread_cancel(), the thread will exit and return to the pthread_join(),
who can tell me what's wrong with my code?
Don't put cleanup_push and _pop inside the while loop. Don't call them more than once. If you look at them, they are macros that wrap the code between them in { }. They setup a longjump that is used when you call pthread_cancel.
pthread_cleanup_pop(1) tells the pthread library to not only pop the cleanup entry off the stack, but to also execute it. So that call will also implicitly call:
pthread_mutex_unlock(&mutexCmd);
Since you've already unlocked the mutex, that call has undefined behavior (assuming the mutex type is PTHREAD_MUTEX_NORMAL). I imagine that call is just never returning or something.
Note that your code has other problems handing the cleanup - if you execute the continue for the loop, you'll call pthread_cleanup_push() a second time (or more), which will add another cleanup context.
There may be other problems (I'm not very familiar with pthread_cancel()).
My pthread_detach calls fail with a "Bad file descriptor" error. The calls are in the destructor for my class and look like this -
if(pthread_detach(get_sensors) != 0)
printf("\ndetach on get_sensors failed with error %m", errno);
if(pthread_detach(get_real_velocity) != 0)
printf("\ndetach on get_real_velocity failed with error %m", errno);
I have only ever dealt with this error when using sockets. What could be causing this to happen in a pthread_detach call that I should look for? Or is it likely something in the thread callback that could be causing it? Just in case, the callbacks look like this -
void* Robot::get_real_velocity_thread(void* threadid) {
Robot* r = (Robot*)threadid;
r->get_real_velocity_thread_i();
}
inline void Robot::get_real_velocity_thread_i() {
while(1) {
usleep(14500);
sensor_packet temp = get_sensor_value(REQUESTED_VELOCITY);
real_velocity = temp.values[0];
if(temp.values[1] != -1)
real_velocity += temp.values[1];
} //end while
}
/*Callback for get sensors thread*/
void* Robot::get_sensors_thread(void* threadid) {
Robot* r = (Robot*)threadid;
r->get_sensors_thread_i();
} //END GETSENSORS_THREAD
inline void Robot::get_sensors_thread_i() {
while(1) {
usleep(14500);
if(sensorsstreaming) {
unsigned char receive;
int read = 0;
read = connection.PollComport(port, &receive, sizeof(unsigned char));
if((int)receive == 19) {
read = connection.PollComport(port, &receive, sizeof(unsigned char));
unsigned char rest[54];
read = connection.PollComport(port, rest, 54);
/* ***SET SENSOR VALUES*** */
//bump + wheel drop
sensor_values[0] = (int)rest[1];
sensor_values[1] = -1;
//wall
sensor_values[2] = (int)rest[2];
sensor_values[3] = -1;
...
...
lots more setting just like the two above
} //end if header == 19
} //end if sensors streaming
} //end while
} //END GET_SENSORS_THREAD_I
Thank you for any help.
The pthread_* functions return an error code; they do not set errno. (Well, they may of course, but not in any way that is documented.)
Your code should print the value returned by pthread_detach and print that.
Single Unix Spec documents two return values for this function: ESRCH (no thread by that ID was found) and EINVAL (the thread is not joinable).
Detaching threads in the destructor of an object seems silly. Firstly, if they are going to be detached eventually, why not just create them that way?
If there is any risk that the threads can use the object that is being destroyed, they need to be stopped, not detached. I.e. you somehow indicate to the threads that they should shut down, and then wait for them to reach some safe place after which they will not touch the object any more. pthread_join is useful for this.
Also, it is a little late to be doing that from the destructor. A destructor should only be run when the thread executing it is the only thread with a reference to that object. If threads are still using the object, then you're destroying it from under them.