Binding multiple pthreads, each to the same member function of a different object from the same class - pthreads

I have bound multiple pthreads to independent member function of independent objects from the same class.
I had to use of a static member function as a helper since it is not possible to bind a member function directly to a pthread in C++; however, my application behaves strangely and I am suspicious to the use of this static function, since this static function is shared between all objects of the same class.
Is this type of usage right? Is there any alternative solution?
I appreciate to hear any guidance.
class Region
{
public:
Region();
void Init();
void Push_Tuple(int int_value, float float_value, bool tuple_source);
static void *Read_Tuple_R_Process_S_Update_helper(void *context)
{
return ((Region *)context)->Read_Tuple_R_Process_S_Update();
}
void* Read_Tuple_R_Process_S_Update();
static void *Read_Tuple_S_Process_R_Update_helper(void *context)
{
return ((Region *)context)->Read_Tuple_S_Process_R_Update();
}
void* Read_Tuple_S_Process_R_Update();
};
int main(){
Region regions[THREAD_COUNT*2];
for(int i=0; i < THREAD_COUNT*2; i++){
regions[i].Init();
}
pthread_t thread_ID[THREAD_COUNT*2];
void* exit_status;
for(int i=0; i < THREAD_COUNT; i++){
pthread_create(&thread_ID[i], NULL, &Region::Read_Tuple_R_Process_S_Update_helper, &regions[i]);
}
for(int i=THREAD_COUNT; i < THREAD_COUNT*2; i++){
pthread_create(&thread_ID[i], NULL, &Region::Read_Tuple_S_Process_R_Update_helper, &regions[i]);
}
for(int i=0; i < THREAD_COUNT*2; i++){
pthread_join(thread_ID[i], &exit_status);
}
return 0;
}

Although I was suspected to the binding that I described, it was not the source of my problem and it works correctly.
The problem was waiting while loops which were affected by optimizer! Using volatile keyword solved my problem.

Related

MQL4 Send objects array as function parameter

I had the function as a class member with an array of my custom object as a parameter:
class Stochastic { ... some class which sent into initializeStochastics method as param };
class StochasticInitializer {
public:
Properties *properties[8];
public:
StochasticInitializer(void) {
this.properties = ...
}
public:
void initializeStochastics(Stochastic& *stochastics[]) { // This param is my problem
for (int i = 0 ;i < ArraySize(properties); i++) {
if (properties[i].enabled) {
stochastics[i] = new Stochastic(properties[i]);
}
}
}
};
My errors:
'&' - comma expected
']' - declaration without type
']' - comma expected
'initializeStochastics' - wrong parameters count
'stochastics' - undeclared identifier
I take syntax from here, but perhaps it solution for MQL5.
Can I send an array of class instances as a method parameter in MQL4? If "yes" - how, if no - it answers too.
Everything works (almost works) just decide whether you are going to create an global array or with pointer access (need to delete it after you finish). Here is example of pointers. Also, please provide MCVE next time, because someone needs to write all that useless stuff like properties&stoch classes to make it testable.
class Properties
{
public:
bool enabled;
int periodK;
Properties(bool _enabled,int k):enabled(_enabled),periodK(k){}
~Properties(){}
};
class Stochastic
{
public:
int periodK;
Stochastic(){}
~Stochastic(){}
Stochastic(Properties *prop):periodK(prop.periodK){}
double get(const int shift,const int buffer=0)const{return iStochastic(_Symbol,0,periodK,3,3,MODE_SMA,STO_LOWHIGH,buffer,shift);}
};
class StochasticInitializer
{
public:
Properties *properties[8];
StochasticInitializer()
{
Deinit();
properties[0]=new Properties(true,5);
properties[1]=new Properties(true,13);
properties[2]=new Properties(true,14);
properties[3]=new Properties(true,15);
properties[4]=new Properties(true,16);
properties[5]=new Properties(true,17);
properties[6]=new Properties(true,18);
properties[7]=new Properties(false,19);
}
~StochasticInitializer(){Deinit();}
void Deinit(const int reason=0){ for(int i=0;i<ArraySize(properties);i++)delete(properties[i]); }
void initializeStochastics(Stochastic *&stochastics[])// THIS IS WHAT YOU NEED IN CASE OF POINTERS
{
for(int i=0;i<ArraySize(properties);i++)
{
if(properties[i].enabled)
{
stochastics[i]=new Stochastic(properties[i]);
}
}
}
};
StochasticInitializer initializer;
void OnTick()
{
Stochastic *array[8]; //THIS IS ARRAY OF POINTERS
initializer.initializeStochastics(array);
for(int i=0;i<ArraySize(array);i++)
{
printf("%i %s: %d %s",__LINE__,__FILE__,i,CheckPointer(array[i])==POINTER_INVALID ? "null" : (string)array[i].periodK);
}
for(int i=ArraySize(array)-1;i>=0;i--)delete(array[i]);//DELETING POINTERS
ExpertRemove();
}

MPLAB: XC8: Cannot assign struct variable

I am trying to compile the following code in MPLab v5.10 using XC8 for a PIC18.
The code is as follows:
struct vec2i {
int x;
int y;
};
void main(void) {
static struct vec2i array[10];
int i;
for(i = 0; i < 10; ++i) {
array[i] = {0, 0};
}
return;
}
This yields the following error:
newmain.c:11:20: error: expected expression
array[i] = {0, 0};
This code compiles just fine on my native gcc compiler.
If I change the code to the following, the error goes away.
struct vec2i {
int x;
int y;
};
void main(void) {
static struct vec2i array[10];
int i;
for(i = 0; i < 10; ++i) {
// array[i] = {0, 0};
array[i].x = 0;
array[i].y = 0;
}
return;
}
I am using the free version of XC8, version 2.05. Is this a bug, or am I overlooking something with regards to the PIC architecture?
Looks like I don't know C as well as I thought; The following post clarifies the problem I was facing: Struct initialization in C with error: expected expression
The corrected code reads as follows:
struct vec2i {
int x;
int y;
};
void main(void) {
static struct vec2i array[10];
int i;
for(i = 0; i < 10; ++i) {
array[i] = (struct vec2i){0, 0};
}
return;
}
Note that this kind of workaround is only available under C99. Selecting C90 from MPLAB verifies this (the above code fails to compile under C90).
As for the code working on my machine, I was actually using g++, which has support for extended initialier lists since c++11, which is enabled by default.

StreamTransformer in Dart being skipped?

I'm not sure if I'm not understanding this correctly, but here's my code. I'm trying to get the StreamTransformer to act on the stream, but the values still come out the other end untouched.
Note: I added the .map() function, which does nothing, just to make sure it wasn't a missing map function that was my issue. I'm leaving it here just in case.
import 'dart:async';
void main() {
int count = 0;
var counterController = new StreamController();
counterController.stream.listen((value) => print(value));
void increment() {
counterController.add(count++);
}
final transformToString =
new StreamTransformer.fromHandlers(handleData: (number, sink) {
if (number.runtimeType == int) {
sink.add("The counter is at $number!");
} else {
sink.addError("$number is not an int!");
}
});
counterController.stream.map((input) => input).transform(transformToString);
for(int i=0; i < 10; i++){
increment();
}
}
Link to the code in DartPad
As was mentioned by my instructor, the transform function creates out a new stream. So I have to attach a listener to the transformed stream, I can't expect transformed values to come out of the old stream. So the modified code below works.
import 'dart:async';
void main() {
...
counterController.stream.map((input) => input)
.transform(transformToString).listen(print);
for(int i=0; i < 10; i++){
increment();
}
}

pthread_join causing seg fault

As part of a pthreads tutorial exercise I wrote a program to create 10 threads than to join the 10 threads. The program runs and prints the output however it seems that on the first call to pthread_join it causes a segmentation fault. I am not sure why this is occurring. I tried searching on web, however most issues where concerning invalid pointers passed to the function. I am not sure if this is the same issue with my code, as I am not seeing it easily.
if anyone can help me, I certainly would appreciate it :)
code is below:
#include <stdio.h>
#include <pthread.h>
#define NTHREADS 10
void *thread_function(void *arg)
{
int i;
int *coming = (int*) arg;
for(i=0; i<5; i++)
printf("Hello, World (thread %d)\n", *coming);
return NULL;
}
int main(void)
{
int i;
void *exit_status;
int retVal;
pthread_t pthread_array[NTHREADS];
int randVals[10] = {23,5,17,55,9,47,69,12,71,37};
printf("threads are created\n");
for(i=0; i<10; i++)
{
retVal=pthread_create(&pthread_array[i], NULL, thread_function, &randVals[i]);
printf("pthread_create %d retVal=%d\n", i, retVal);
}
printf("threads are joined\n");
for(i=0; i<10; i++)
{
retVal= pthread_join(pthread_array[i], &exit_status);
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
}
printf("all threads have ended\n");
return 0;
}
This is the problem
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
your thread function returns NULL, and so this is the value stored in exit_status. So now in your printf you do this
*((int *)exit_status
you are casting this NULL pointer to a int* and then dereferencing it. Dereferencing NULL pointers is not a good idea. See this question for a fuller example of how to use exit_status What does exactly the "status" in pthread_join represent and how to query it
*((int *)exit_status));
If the thread function returns NULL (which it does), this will try to dereference it. Before doing so, you should test exit_status:
pthread_join(...);
if (exit_status != NULL)
/* Safe to use. */

updating to ARC errors

I am trying to update a project to ARC. Though I've seen a few posts on updating to ARC, none of the posts I've seen handle this specific issue. I've got multiple errors, most saying:
ARC Issue
Pointer to non-const type 'id' with no explicit ownership
pointing to line
CCARRAY_FOREACH(children_, item)
in the CCMenu.m class. Please help.
Updated:
After restarting Xcode the above issue is no longer found at
CCARRAY_FOREACH(children_, item)
but was found in the ccCArray.h class at the lines I've commented as
// Arc Issue
Several other errors have surface.
The warning sign:
Arc Issue
Destination for this '_builtin__memmove_chk' call is a pointer to ownership-qualified-type 'autoreleasing-id'
appears wherever is memmove called in the code.
another error:
ARC Casting Rules
Implicit conversion of C pointer type 'void *' to Objective-C pointer type 'id' requires a bridged cast
appears at the lines I've commented as:
//ARC Casting Rules
ccCArray.h:
#ifndef CC_ARRAY_H
#define CC_ARRAY_H
#import <Foundation/Foundation.h>
#import <stdlib.h>
#import <string.h>
#pragma mark -
#pragma mark ccArray for Objects
// Easy integration
#define CCARRAYDATA_FOREACH(__array__, __object__) \
__object__=__array__->arr[0]; for(NSUInteger i=0, num=__array__->num; i<num; i++, __object__=__array__->arr[i]) \
typedef struct ccArray {
NSUInteger num, max;
id *arr; // Arc Issue
} ccArray;
/** Allocates and initializes a new array with specified capacity */
static inline ccArray* ccArrayNew(NSUInteger capacity) {
if (capacity == 0)
capacity = 1;
ccArray *arr = (ccArray*)malloc( sizeof(ccArray) ); // Arc Issue
arr->num = 0;
arr->arr = (id*) malloc( capacity * sizeof(id) );
arr->max = capacity;
return arr;
}
static inline void ccArrayRemoveAllObjects(ccArray *arr);
/** Frees array after removing all remaining objects. Silently ignores nil arr. */
static inline void ccArrayFree(ccArray *arr)
{
if( arr == nil ) return;
ccArrayRemoveAllObjects(arr);
free(arr->arr);
free(arr);
}
/** Doubles array capacity */
static inline void ccArrayDoubleCapacity(ccArray *arr)
{
arr->max *= 2;
id *newArr = (id *)realloc( arr->arr, arr->max * sizeof(id) ); // Arc Issue
// will fail when there's not enough memory
NSCAssert(newArr != NULL, #"ccArrayDoubleCapacity failed. Not enough memory");
arr->arr = newArr;
}
/** Increases array capacity such that max >= num + extra. */
static inline void ccArrayEnsureExtraCapacity(ccArray *arr, NSUInteger extra)
{
while (arr->max < arr->num + extra)
ccArrayDoubleCapacity(arr);
}
/** shrinks the array so the memory footprint corresponds with the number of items */
static inline void ccArrayShrink(ccArray *arr)
{
NSUInteger newSize;
//only resize when necessary
if (arr->max > arr->num && !(arr->num==0 && arr->max==1))
{
if (arr->num!=0)
{
newSize=arr->num;
arr->max=arr->num;
}
else
{//minimum capacity of 1, with 0 elements the array would be free'd by realloc
newSize=1;
arr->max=1;
}
arr->arr = (id*) realloc(arr->arr,newSize * sizeof(id) ); // Arc Issue
NSCAssert(arr->arr!=NULL,#"could not reallocate the memory");
}
}
/** Returns index of first occurence of object, NSNotFound if object not found. */
static inline NSUInteger ccArrayGetIndexOfObject(ccArray *arr, id object)
{
for( NSUInteger i = 0; i < arr->num; i++)
if( arr->arr[i] == object ) return i;
return NSNotFound;
}
/** Returns a Boolean value that indicates whether object is present in array. */
static inline BOOL ccArrayContainsObject(ccArray *arr, id object)
{
return ccArrayGetIndexOfObject(arr, object) != NSNotFound;
}
/** Appends an object. Bahaviour undefined if array doesn't have enough capacity. */
static inline void ccArrayAppendObject(ccArray *arr, id object)
{
arr->arr[arr->num] = [object retain];
arr->num++;
}
/** Appends an object. Capacity of arr is increased if needed. */
static inline void ccArrayAppendObjectWithResize(ccArray *arr, id object)
{
ccArrayEnsureExtraCapacity(arr, 1);
ccArrayAppendObject(arr, object);
}
/** Appends objects from plusArr to arr. Behaviour undefined if arr doesn't have
enough capacity. */
static inline void ccArrayAppendArray(ccArray *arr, ccArray *plusArr)
{
for( NSUInteger i = 0; i < plusArr->num; i++)
ccArrayAppendObject(arr, plusArr->arr[i]);
}
/** Appends objects from plusArr to arr. Capacity of arr is increased if needed. */
static inline void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr)
{
ccArrayEnsureExtraCapacity(arr, plusArr->num);
ccArrayAppendArray(arr, plusArr);
}
/** Inserts an object at index */
static inline void ccArrayInsertObjectAtIndex(ccArray *arr, id object, NSUInteger index)
{
NSCAssert(index<=arr->num, #"Invalid index. Out of bounds");
ccArrayEnsureExtraCapacity(arr, 1);
NSUInteger remaining = arr->num - index;
if( remaining > 0)
memmove(&arr->arr[index+1], &arr->arr[index], sizeof(id) * remaining );
arr->arr[index] = [object retain];
arr->num++;
}
/** Swaps two objects */
static inline void ccArraySwapObjectsAtIndexes(ccArray *arr, NSUInteger index1, NSUInteger index2)
{
NSCAssert(index1 < arr->num, #"(1) Invalid index. Out of bounds");
NSCAssert(index2 < arr->num, #"(2) Invalid index. Out of bounds");
id object1 = arr->arr[index1];
arr->arr[index1] = arr->arr[index2];
arr->arr[index2] = object1;
}
/** Removes all objects from arr */
static inline void ccArrayRemoveAllObjects(ccArray *arr)
{
while( arr->num > 0 )
[arr->arr[--arr->num] release];
}
/** Removes object at specified index and pushes back all subsequent objects.
Behaviour undefined if index outside [0, num-1]. */
static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
{
[arr->arr[index] release];
arr->num--;
NSUInteger remaining = arr->num - index;
if(remaining>0)
memmove(&arr->arr[index], &arr->arr[index+1], remaining * sizeof(id));
}
/** Removes object at specified index and fills the gap with the last object,
thereby avoiding the need to push back subsequent objects.
Behaviour undefined if index outside [0, num-1]. */
static inline void ccArrayFastRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
{
[arr->arr[index] release];
NSUInteger last = --arr->num;
arr->arr[index] = arr->arr[last];
}
static inline void ccArrayFastRemoveObject(ccArray *arr, id object)
{
NSUInteger index = ccArrayGetIndexOfObject(arr, object);
if (index != NSNotFound)
ccArrayFastRemoveObjectAtIndex(arr, index);
}
/** Searches for the first occurance of object and removes it. If object is not
found the function has no effect. */
static inline void ccArrayRemoveObject(ccArray *arr, id object)
{
NSUInteger index = ccArrayGetIndexOfObject(arr, object);
if (index != NSNotFound)
ccArrayRemoveObjectAtIndex(arr, index);
}
/** Removes from arr all objects in minusArr. For each object in minusArr, the
first matching instance in arr will be removed. */
static inline void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr)
{
for( NSUInteger i = 0; i < minusArr->num; i++)
ccArrayRemoveObject(arr, minusArr->arr[i]);
}
/** Removes from arr all objects in minusArr. For each object in minusArr, all
matching instances in arr will be removed. */
static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr)
{
NSUInteger back = 0;
for( NSUInteger i = 0; i < arr->num; i++) {
if( ccArrayContainsObject(minusArr, arr->arr[i]) ) {
[arr->arr[i] release];
back++;
} else
arr->arr[i - back] = arr->arr[i];
}
arr->num -= back;
}
/** Sends to each object in arr the message identified by given selector. */
static inline void ccArrayMakeObjectsPerformSelector(ccArray *arr, SEL sel)
{
for( NSUInteger i = 0; i < arr->num; i++)
[arr->arr[i] performSelector:sel];
}
static inline void ccArrayMakeObjectsPerformSelectorWithObject(ccArray *arr, SEL sel, id object)
{
for( NSUInteger i = 0; i < arr->num; i++)
[arr->arr[i] performSelector:sel withObject:object];
}
#pragma mark -
#pragma mark ccCArray for Values (c structures)
typedef ccArray ccCArray;
static inline void ccCArrayRemoveAllValues(ccCArray *arr);
/** Allocates and initializes a new C array with specified capacity */
static inline ccCArray* ccCArrayNew(NSUInteger capacity) {
if (capacity == 0)
capacity = 1;
ccCArray *arr = (ccCArray*)malloc( sizeof(ccCArray) );
arr->num = 0;
arr->arr = (id*) malloc( capacity * sizeof(id) ); // Arc Issue
arr->max = capacity;
return arr;
}
/** Frees C array after removing all remaining values. Silently ignores nil arr. */
static inline void ccCArrayFree(ccCArray *arr)
{
if( arr == nil ) return;
ccCArrayRemoveAllValues(arr);
free(arr->arr);
free(arr);
}
/** Doubles C array capacity */
static inline void ccCArrayDoubleCapacity(ccCArray *arr)
{
ccArrayDoubleCapacity(arr);
}
/** Increases array capacity such that max >= num + extra. */
static inline void ccCArrayEnsureExtraCapacity(ccCArray *arr, NSUInteger extra)
{
ccArrayEnsureExtraCapacity(arr,extra);
}
/** Returns index of first occurence of value, NSNotFound if value not found. */
static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, void* value)
{
for( NSUInteger i = 0; i < arr->num; i++)
if( arr->arr[i] == value ) return i;
return NSNotFound;
}
/** Returns a Boolean value that indicates whether value is present in the C array. */
static inline BOOL ccCArrayContainsValue(ccCArray *arr, void* value)
{
return ccCArrayGetIndexOfValue(arr, value) != NSNotFound;
}
/** Inserts a value at a certain position. Behaviour undefined if aray doesn't have enough capacity */
static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, void *value, NSUInteger index)
{
NSCAssert( index < arr->max, #"ccCArrayInsertValueAtIndex: invalid index");
NSUInteger remaining = arr->num - index;
// last Value doesn't need to be moved
if( remaining > 0) {
// tex coordinates
memmove( &arr->arr[index+1],&arr->arr[index], sizeof(void*) * remaining );
}
arr->num++;
arr->arr[index] = (id) value;
}
/** Appends an value. Bahaviour undefined if array doesn't have enough capacity. */
static inline void ccCArrayAppendValue(ccCArray *arr, void* value)
{
arr->arr[arr->num] = (id) value;
arr->num++;
}
/** Appends an value. Capacity of arr is increased if needed. */
static inline void ccCArrayAppendValueWithResize(ccCArray *arr, void* value)
{
ccCArrayEnsureExtraCapacity(arr, 1);
ccCArrayAppendValue(arr, value);
}
/** Appends values from plusArr to arr. Behaviour undefined if arr doesn't have
enough capacity. */
static inline void ccCArrayAppendArray(ccCArray *arr, ccCArray *plusArr)
{
for( NSUInteger i = 0; i < plusArr->num; i++)
ccCArrayAppendValue(arr, plusArr->arr[i]); //ARC Casting Rules
}
/** Appends values from plusArr to arr. Capacity of arr is increased if needed. */
static inline void ccCArrayAppendArrayWithResize(ccCArray *arr, ccCArray *plusArr)
{
ccCArrayEnsureExtraCapacity(arr, plusArr->num);
ccCArrayAppendArray(arr, plusArr);
}
/** Removes all values from arr */
static inline void ccCArrayRemoveAllValues(ccCArray *arr)
{
arr->num = 0;
}
/** Removes value at specified index and pushes back all subsequent values.
Behaviour undefined if index outside [0, num-1].
#since v0.99.4
*/
static inline void ccCArrayRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
{
for( NSUInteger last = --arr->num; index < last; index++)
arr->arr[index] = arr->arr[index + 1];
}
/** Removes value at specified index and fills the gap with the last value,
thereby avoiding the need to push back subsequent values.
Behaviour undefined if index outside [0, num-1].
#since v0.99.4
*/
static inline void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
{
NSUInteger last = --arr->num;
arr->arr[index] = arr->arr[last];
}
/** Searches for the first occurance of value and removes it. If value is not found the function has no effect.
#since v0.99.4
*/
static inline void ccCArrayRemoveValue(ccCArray *arr, void* value)
{
NSUInteger index = ccCArrayGetIndexOfValue(arr, value);
if (index != NSNotFound)
ccCArrayRemoveValueAtIndex(arr, index);
}
/** Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
#since v0.99.4
*/
static inline void ccCArrayRemoveArray(ccCArray *arr, ccCArray *minusArr)
{
for( NSUInteger i = 0; i < minusArr->num; i++)
ccCArrayRemoveValue(arr, minusArr->arr[i]); //ARC Casting Rules
}
/** Removes from arr all values in minusArr. For each value in minusArr, all matching instances in arr will be removed.
#since v0.99.4
*/
static inline void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr)
{
NSUInteger back = 0;
for( NSUInteger i = 0; i < arr->num; i++) {
if( ccCArrayContainsValue(minusArr, arr->arr[i]) ) //ARC Casting Rules {
back++;
} else
arr->arr[i - back] = arr->arr[i];
}
arr->num -= back;
}
#endif // CC_ARRAY_H
It looks like you're using a version of cocos2d that isn't compatible with ARC because the ccArray code is missing the ARC fixes and additions. Upgrade to cocos2d 1.1 or newer. Cocos2d 1.0.1 might work as well but I think that version still has some ARC issues.
Or start with a fresh, ARC-enabled cocos2d project and then re-add your code and resources to it.
Easy fix:
Get rid of this “use a raw C-array to store objects”-approach altogether and delete the whole file containing the macros.
Replace it with proper use of (mutable) containers from the Foundation framework, and move on.

Resources