Short Notes on C/C++
Contents
How to clean up after child thread
Even when the child thread shuts down gracefully - i.e. the thread's function returns, or the thread calls pthread_exit() - there might still be a memory leak due to the thread data allocated during the call to pthread_create().
There are 3 options to handle this:
- stop the thread from the creator thread using pthread_cancel(),
- wait for the thread to shut down gracefully, and then pthread_join() with the thread (yes, "join with the stopped thread"); this call returns immediately, and frees up thread's resources,
- have the thread clean up on its own, by pthread_detach()-ing the thread.
Non-blocking IO using sockets
To get a non-blocking IO, you can
- set the socket to non-blocking:
// for fcntl() #include <unistd.h> #include <fcntl.h> // for ioctl() #include <sys/ioctl.h> int set_nonblocking(int fd) { int flags; #if defined(O_NONBLOCK) if (-1 == (flags = fcntl(fd, F_GETFL, 0))) flags = 0; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); #else flags = 1; return ioctl(fd, FIOBIO, &flags); #endif }
- or, you can use MSG_DONTWAIT as flags in the calls to recv(), recvfrom(), send(), and sendto().
Or both... can't hurt. ;-)
Shared libraries on Linux typically name linker name, soname, and real name.
The linker name is typically "libtest.so". The soname is linker name with version, typically "libtest.so.1", and the real name is the name of the file, typically "libtest.so.1.0.3".
In reality, the "libtest.so.1.0.3" would be the actual file, with two links:
libtest.so.1 -> libtest.so.1.0.3 libtest.so -> libtest.so.1
Example
Here's an example of "test_so" library - .h and .c files, how to build and link the .so file, and using this library from Python using ctypes.
test_so.h
#ifndef __TEST_SO__ #define __TEST_SO__ int test_so_string(const char* str); int test_so_int(int i); #endif//__TEST_SO__
test_so.c
#include "test_so.h" #include <string.h> int test_so_string(const char* str) { return strlen(str); } int test_so_int(int i) { return -i; }
Compiling and Linking
gcc -fPIC -O3 -c -Wall test_so.c gcc -shared -Wl,-soname,libtest_so.so.1 -o libtest_so.so.1.0.0 test_so.o -lc
Now, you can create also the "upper links":
ln -s libtest_so.so.1.0.0 libtest_so.so.1 ln -s libtest_so.so.1 libtest_so.so
Using from Python - test_so.py
import ctypes lib = ctypes.CDLL("./libtest_so.so") print "int -> int fcall works" if lib.test_so_int(1) == -1 else "int -> int fcall DOESN'T WORK!" print "string -> int fcall works" if lib.test_so_string("hello there!") == 12 else "string -> int fcall DOESN'T WORK!"
will output:
$ python test_so.py int -> int fcall works string -> int fcall works
See ctypes library for more info.
Notes
If your library needs for it's work to be used together with some other shared/dynamic library, you need to include -Wl,-export-dynamic option when creating the object file, so that linker exports all of the symbols, making it clear what all needs to be added for the library to work properly in the program that uses your library.
Singleton
Traditional Approach
// Singleton.h class Singleton { private: Singleton() { } Singleton(const Singleton&) { } Singleton& operator=(const Singleton&) { } ~Singleton() { } static Singleton* inst; public: static Singleton* instance(); };
// Singleton.cpp #include "Singleton.h" Singleton* Singleton::inst = NULL; Singleton* Singleton::instance() { return inst ? inst : inst = new Singleton; }
Stack-based Singleton
I usually prefer this version over the dynamically allocated one, as the destructor will be called (at some point in time), and allows you to free up all resources obtained during the lifetime - esp. close files, sockets, etc.
class Singleton { private: Singleton(); Singleton(const Singleton&); Singleton& operator=(const Singleton&); ~Singleton(); // ... public: static Singleton& instance() { static Singleton inst; // constructed on the first call return inst; } // ... };