passing an ofstream object to a thread function via pthread_create - pthreads

I want to pass an ofstream object to a thread using pthread_create function.
Let's say I create an object like this in my main(int argc, char *argv[]) function.
ofstream file1(argv[1], fstream::out|fstream::app);
pthread_t tid;
pthread_create(&tid, NULL, function1, (void *)args);
And the function1 is defined as.
void function1(void *input)
{
ofstream file;
file = ??
file << "Hello" << endl;
}
How can I access "file1.txt" created in the main function via the file object?

There are several ways to pass the object. One would be to make it global, then then it's very straightforward for function1() to access it. Or you can pass a pointer to it as the thread's argument. Cast it to void* in the pthread_create() call and cast it back in the thread function.
void* function1(void *input) {
ofstream* file = static_cast<ofstream*>(input);
*file << "Hello" << endl;
return NULL;
}
ofstream file1("./file1.txt", fstream::out|fstream::app);
pthread_t tid;
pthread_create(&tid, NULL, function1, static_cast<void*>(&file1));
Be warned, there is a common bug that this pattern often leads to! The ofstream will be destructed when the scope it was created in ends, which is in the thread that called pthread_create(). If the thread running function1() is still running, it could use the pointer to the now destructed ofstream.
You need to insure that the ofstream remains alive until the other thread is done with it. One way would be to give it static storage duration, either as a static local variable or as a global variable. Another would to allocate it with new and then delete it in the thread that is using it. Or you could insure that the created thread is joined before the ifstream leaves scope.
Using new and delete:
void start(void) {
ofstream* file1 = new ofstream("file1.txt", fstream::app);
pthread_create(&tid, NULL, function1, static_cast<void*>(file1));
file1 = NULL; // function1 owns this now, shouldn't be used here anymore
}
void* function1(void* arg) {
ofstream* file1 = static_cast<ofstream*>(arg);
delete file1;
}
Joining before the ofstream leaves scope:
void start(void) {
{
ofstream file1("file1.txt", fstream::app);
pthread_create(&tid, NULL, function1, static_cast<void*>(file1));
// stuff
pthread_join(tid);
// now it's safe for file1 to be destructed.
}
}
Also note that the thread function should return void*, not void. Also it should be declared as extern "C" so that it will have the correct ABI when the C pthreads library calls it. Notice how in the new/delete example, I set the pointer to NULL after starting the thread. This is because you can not assume it is safe to access the ofstream from more than one thread at a time. By setting it to NULL, only the function1 thread will be able to access it.
Consider also, maybe it makes more sense to pass the name to the thread and have it open the file? This solves the issues around the lifetime of the object vs the lifetime of the thread using it.

Related

Is it possible to get class name when implementing malloc_logger function in iOS?

From here, we know if malloc_logger global function is defined, it will be called whenever there is a malloc or free operation. I want to use it to record memory allocations in my app like this:
typedef void(malloc_logger_t)(uint32_t type,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3,
uintptr_t result,
uint32_t num_hot_frames_to_skip);
extern malloc_logger_t *malloc_logger;
void my_malloc_stack_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip);
malloc_logger = my_malloc_stack_logger;
void my_malloc_stack_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip)
{
// do my work
}
In my_malloc_stack_logger, I can directly get the allocated size and address. But how about object types? I want to record the class name if it is an NSObject instance. Is it possible to get this information?
After playing around with the hook, it looks like what you want to achieve is not quite possible.
First problem here is that if you try to read a class name from within this function (by calling any of object_getClassName, class_getName
or NSStringFromClass), this action on its own tends to trigger new allocations. That apparently happens because some Cocoa classes load lazily. I noticed however that when requesting all classes with objc_getClassList it makes a lot of preliminary allocations that helps to avoid them later on. So my idea is to cache all class names before subscribing to the allocations hook and refer to the cached values when needed. For the storage I used Apple's CFMutableDictionary:
CFMutableDictionaryRef objc_class_records;
void refresh_objc_class_list(void) {
pthread_mutex_lock(&objc_class_records_mutex);
if (objc_class_records) {
CFRelease(objc_class_records);
}
objc_class_records = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
// The buffer needs to accomodate at least 26665 instances
static const unsigned buffer_length = 100000;
Class registered_classes[buffer_length];
objc_getClassList(registered_classes, buffer_length);
for (unsigned i = 0; i < buffer_length; ++i) {
if (!registered_classes[i]) {
break;
}
const Class class = registered_classes[i];
const CFStringRef class_name = CFStringCreateWithCString(kCFAllocatorDefault, class_getName(class), kCFStringEncodingUTF8);
CFDictionarySetValue(objc_class_records, class, class_name);
CFRelease(class_name);
}
}
Be advised that you don't want to have it called when the malloc logger is enabled (especially from within the hook itself).
Now you need to obtain a Class instance from the Objective-C objects. Depending on the type of allocation, the pointer argument goes to fifth or third parameter:
void my_malloc_logger(uint32_t type, uintptr_t param0, uintptr_t param1, uintptr_t param2,
uintptr_t param3, uint32_t frames_to_skip) {
void *ptr = NULL;
unsigned size = 0;
switch (type) {
case MALLOC_OP_MALLOC:
case MALLOC_OP_CALLOC:
ptr = (void *)param3;
size = (unsigned)param1;
break;
case MALLOC_OP_REALLOC:
ptr = (void *)param3;
size = (unsigned)param2;
break;
case MALLOC_OP_FREE:
ptr = (void *)param1;
break;
}
id objc_ptr = (id)ptr;
Class objc_class = object_getClass(objc_ptr);
if (!objc_class) {
return;
}
const CFStringRef class_name;
const bool found = CFDictionaryGetValueIfPresent(objc_class_records, objc_class, (const void **)&class_name);
if (found) {
const static unsigned name_max_length = 256;
char c_class_name[name_max_length];
if (CFStringGetCString(class_name, c_class_name, name_max_length, kCFStringEncodingUTF8)) {
const char *alloc_name = alloc_type_name(type);
nomalloc_printf_sync("%7s: Pointer: %p; Size: %u; Obj-C class: \"%s\"\n", alloc_name, objc_ptr, size, c_class_name);
}
}
}
And now why it won't work as expected:
object_getClass is not able to tell whether a pointer is an object of Cococa classes at the time of allocation (it will find the class, however, when the object is already allocated, e.g. before deallocation). Thus, the following code:
[NSObject new];
Will produce output similar to this:
CALLOC: Pointer: 0x600000600080; Size: 16
FREE: Pointer: 0x600000600080; Size: 0; Obj-C class: "NSObject"
Most of the standard Cocoa classes are in fact so-called Class Clusters and under the hood the actual allocation happens for an instance of a private class (which is not always recognisable by its public interface), thus this information is incomplete and sometimes misleading.
There are also many other factors which need to be taken into account (which i didn't cover here because it's beyond the question asked): the way you output data to standard output should not cause allocation by itself; the logging needs synchronisation since allocation happens a lot from any number of threads; if you want to enable/disable recording the Objective-C classes (or update the cache occasionally) access to the storage also needs to be synchronised.
Having that said if you are satisfied with what can be done with it, feel free to refer to the repository I made where this approach is already implemented in a form of a static library.

Use thread local store lua_State

I need to use Lua in IOCP, and use Thread local Storage to store lua_State *. I should use lua_close() destroy the lua_State before the thread destroyed, but the work thread is created by IOCP.
The question is when is the right time to call lua_close?
static DWORD WINAPI work_thread_proc(void* parameter){
lua_State * L = TlsGetValue(tls_lua_key);
if(NULL = L){
L=luaL_newstate();
//DO some initialze for L...
TlsSetValue(tls_lua_key,L);
}
}
//..... other place call
QueueUserWorkItem(&work_thread_proc, req, WT_EXECUTELONGFUNCTION);
you can use it like this.
__declspec(thread) lua_State *tls_LuaState = NULL;
// close lua state on exit thread.
void NTAPI TLS_CloseLuaState(PVOID module, DWORD reason, PVOID reserved)
{
if(NULL != ){
lua_close(tls_LuaState);
}
}
#pragma section(".CRT$XLB",long,read)
__declspec(allocate(".CRT$XLB"))
PIMAGE_TLS_CALLBACK p_thread_callback_base = TLS_CloseLuaState;

Not able to setting thread scope.

I am learning about pthreads,I want to set the scope of a thread so for setting scope I used pthread_attr_setscope() API but when I try to get scope of a thread using pthread_attr_getscope() API it all ways return me 0 regardless what ever scope I set(either PROCESS_SCOPE/SYSTEM_SCOPE). For more information please find code below.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
int ret=0;
int mypolicy=-1;
int iscope=-1;
ret = pthread_attr_init (&attr);
pthread_attr_setschedpolicy(&attr,SCHED_RR);
// BOUND behavior - Creating SYSTEM_SCOPE thread
ret = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
//Unbound behaviour - Creating process scope thread
ret = pthread_attr_setscope(&attr,PTHREAD_SCOPE_PROCESS);
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
printf("Return code from pthread_create() is %d\n", rc);
printf("Return value of getschedule policy = %d \n",pthread_attr_getschedpolicy(&attr, &mypolicy));
printf("policy = %d \n",mypolicy);
printf("Return value of getscope = %d \n",pthread_attr_getscope(&attr,&iscope));
printf("scope = %d \n",iscope);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
_exit(-1);
}
}
pthread_exit(NULL);
}
I don't know why every time I get the same value of 'iscope' regardless what ever scope I set(either PROCESS_SCOPE/SYSTEM_SCOPE).
You don't check for errors in your pthread_attr_setscope calls. Put
if (ret) perror("pthread_attr_setscope");
immediately after both calls, and see what it prints. (It may be that your OS does not support one or other of the scheduling modes.)
You call pthread_attr_setscope twice in a row on the same pthread_attr_t with two different scope constants. This cannot possibly be what you want.
You need to pass the pthread_attr_t as the second argument to pthread_create, instead of the NULL you have there, for the changed setting to have any effect at all.
Once you make that change, the scheduling policy will apply to the just-created thread, but pthread_attr_getscope is being called in the main thread. Move it to PrintHello if you want to know the policy for the just-created thread.
You never used your ret variable, so the gcc compiler complained about that (I used -Wall).
Pick a scope -- you've set it twice, sequentially, as zwol mentioned
However, you don't need to use pthread_attr_getscope in the thread itself; the pthread_attr_getscope function simply reports on what's been set in the attribute.
Use pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED); - on systems that support multiple contention scopes, this call is needed to get pthread_create to honor the scheduler attribute. Otherwise, the new thread will simply inherit the main thread's scope.
If you're using Linux - Linux only supports PTHREAD_SCOPE_SYSTEM, so trying to set PTHREAD_SCOPE_PROCESS is, essentially, just ignored

what is wrong with following pthread program?

I am not able to execute pthreads program in c. Please tell me what is wrong with the following program. I am neither getting any error nor expected output.
void *worker(void * arg)
{
int i;
int *id=(int *)arg;
printf("Thread %d starts\n", *id );
}
void main(int argc, char **argv)
{
int thrd_no,i,*thrd_id,rank=0;
void *exit_status;
pthread_t *threads;
thrd_no=atoi(argv[1]-1);
thrd_id= malloc(sizeof(int)*(thrd_no));
threads=malloc(sizeof(pthread_t)*(thrd_no));
for(i=0;i<thrd_no;i++)
{
rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
}
for(i=0;i<thrd_no;i++)
{
pthread_join(threads[i], &exit_status);
}
}
thrd_no = atoi(argv[1] - 1); likely doesn't do what you intended; the way argv is normally passed into a new process and parsed into a C array, argv[1] - 1 is probably pointing at \0 (specifically, the \0 at the end of argv[0]). (More generally, indexing backwards off the start of a string is rarely correct.) The result is that atoi() will return 0 and no threads will be created. What did you actually intend to do there?
You are passing the same address &rank to each thread, so id and *id is the same for all your worker-s.
You should better allocate on the heap the address you pass to each worker routine.
You might also include <stdint.h and use intptr_t, e.g.
void worker (void* p)
{
intptr_t rk = (intptr_t) p;
/// etc
}
and call
intptr_t rank = i + 1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, (void*)rank);
You should learn to use a debugger and compile with all warnings and debug information, i.e. gcc -Wall -g (and improve your code till it gets no warnings, then use gdb)
code segment rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
will produce race condition.

No cout printing in pthread starting function

i'm new here and noob with pthread programming.
My problem is in a C++ class, that i'm trying to create to encapsulate a thread.
Reading around i'd seen that when i create a pthread, i need to pass a C function to pthread_create that it runs on startup... So, when the pthread runs that function it doesn't cout the message on stdout!
But it's better if you see the code:
(obviously it's copy and pasted from an internet tutorial ^^)
void *runAtStart( void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
Thread::Thread() {
pthread_t threads[1];
int rc;
long t;
for(t=0; t<1; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, runAtStart, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
// exit(-1);
}
}
}
in the main i call this as:
int main()
{
Thread *th=new Thread();
return 0;
}
the output generated is:
In main: creating thread 0
i hope that someone has understood!
sorry for my English! :)
Inzirio
Your program runs fine. The problem you're seeing is that your main() function returns before your thread can actually run, and this causes your program to exit.
A simple way to prove this is to add sleep(5); in main(), prior to your return call. A better way is to find a manner to cause main() to wait until all of its threads have completed before it returns. One reasonable manner to do that is to add a destructor to your Thread class that performs a pthread_join, and be sure you actually call the destructor: delete th;

Resources