Archive

Posts Tagged ‘tutorial’

POSIX Threads – Threading with C : Part 1

July 27th, 2009 Danny 3 comments

General

A Thread generally, is a set of instructions, that can be scheduled to run by the OS. Threads can be considered as process children, since they are created from inside a process, but a thread runs independent from the parent process. The only way they can affect each other is when a process is killed, so all child threads are killed too.

On single-processor or single-core systems, as you can imagine, two sets of instructions cannot be executed in the same time, so the processor  switches between them all the time, and in this way, making it look like they happen simultaneously.

On the other hand, multi-processor or multi-core systems, can really execute many sets of instructions in the same time, by assigning each processor / core a set.

Threads vs Processes

Processes are independent, while a thread’s execution, depends weather it’s parent is alive.

Processes use their own memory and carry many state information, while threads share their state and memory, thus making them easy for the OS to initialize.

Communication between threads is easier and faster than processes.

A big problem

peerThreads

Thread creation over time

Consider a process with two child threads. As we said, threads share the same memory. So, what happens when the two threads try to write on the same memory block? That is the main problem of parallel-computing. You might say that the odds for this to happen are way too low, but in fact, this is one of the biggest problems of big applications, which use threads to make use of multi-processor / core systems. Lately there are many ideas developed in order to bypass this problem, but that’s out of the scope of this post. Check links during the post for more information.

For the developer

Okay, since we are aware of the general idea how threads work, lets try to find out how our applications can take advantage of threading.

There are many threading standards / techniques, but we are going to stick with the most used. POSIX Threads, or pthreads. POSIX stands for “Portable Operating System Interface for Unix” and is a set of standards define by the IEEE, about API’s for Unix. pthreads are commonly used on Unix or Unix-like OS’es, but there are various implementations for Windows too, like pthreads-w32.

pthreads, defines a C library, usable with the header. This is the library we will be using to make our threaded program. Lets see a sample Hello World threaded program source :

[ helloworld_thread.c ]

[c]
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5

//callback function.
void hello() {
printf("Im a thread!\n");
pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS]; //Declaring 5 threads.
int rc, t;
//Cycling through threads[5] to pthread_create() each thread.
for(t=0; t < NUM_THREADS; t++) {
printf("Initializing thread %d\n", t);
rc = pthread_create(&threads[t], NULL, (void *)hello, NULL); //creating each thread.
if (rc != 0){ //if pthread_create() doesn’t return 0, then we have error.
printf("ERROR; return code from pthread_create() is %d\n", rc);
return -1;
}
}
pthread_exit(NULL);
return 0;
}
[/c]

Analyzing

Let’t examine the new functions..

[c light="true"]int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);[/c]

  1. pthread_t *thread, a pointer to a pthread.
  2. const pthread_attr_t *attr – Attributes concerning the thread, set NULL for default attributes.
  3. void *( *start_routine)(void *) – Pointer to (void *)function that will be called by the thread.
  4. void *arg – Pointer to argument to provide to the callback function.

[c light="true"]void pthread_exit(void *retval);[/c]

This function terminates the thread with return value of void *retval.

Compiling

In order to compile a C source code using <pthread.h> we need to include the flag -pthread to our compiler, so the compile command should look like this :

[c light="true"]gcc -pthread -o helloworld_thread helloworld_thread.c[/c]

Passing Arguments

The pthread_create() function doesnt allow us to pass more than one argument to the callback function, so if we need to pass more, we have to wrap them inside a struct. Let’s see an example :

[ pthread_argument.c ]

[c]

#include <pthread.h>
#include <stdio.h>

typedef struct FOO {
int i;
int y;
} foo;

void hello(void *arg) {
foo bar = *(foo*)(arg);
printf( "This is coming from a thread:\n");
printf("arg.i = %d\narg.y = %d\n", bar.i, bar.y);
pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
foo bar;
bar.i = 5;
bar.y = 6;
pthread_t mythread;
int rc, t;
printf("Initializing thread!\n");
rc = pthread_create(&mythread, NULL, (void *)hello, (void *)&bar);
if (rc != 0){
printf("ERROR; return code from pthread_create() is %d\n", rc);
return -1;
}
pthread_exit(NULL);
return 0;
}
[/c]

Passing only one argument is easy, you just cast it to (void *) before the call, and then cast it back to it's normal type from inside the callback function. But since i want to pass more arguments, i pass the struct as argument.

Resources : [ computing.llnl.gov, yolinux.com ]

Incoming Part 2 : Advanced thread parameters, joining / detaching / killing threads.

As always, you can subscribe via RSS or follow wedevblog on twitter for the latest development posts!

#include <pthread.h>
#include <stdio.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];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }
   pthread_exit(NULL);
}
  • Share/Bookmark
Categories: dev Tags: , , , ,

C Socket Programming : Part 2

July 24th, 2009 Danny 1 comment
C Scocket Programming : Part 1

R.I.P. IPv4

IPv4 ( Internet Protocol Version 4 ) is the current, most used Internet Protocol, officially described in September 1981 by the IETF, providing 4,294,967,296 (232) addresses.

Address Exhaustion

The biggest problem of IPv4 is the address exhaustion. Back at 1980 when it was defined, nobody could imagine the incredible rate the internet grows. Nowdays every embedded device ( mobile phones, PDAs, palmtops ) is a part of the internet, thus more and more addresses need to be allocated.

Welcome IPv6

IPv6 was defined in December 1998 by the IETF, almost 20 years after the release of IPv4.

IPv6 is the next-generation Internet Protocol, designated as the successor of IPv4 which still dominates the biggest part of the internet…. For now :)

IPv6 addresses use an 128-bit encoding, thus providing about 3.4×1038 addresses and this is the main advantage of it, considering the IPv4 ( 32-bit encoding ) adrress exhaustion.

It also implements new features, additions and many more advantages but that’s not what we are here to cover :) You can read the wikipedia links for more information.

IPv6 and Network Programming

Since IPv6 will be the new internet protocol, and is already defined, why make our applications with only IPv4 in mind? We can develop our applications compatible with IPv6, but at the same time, backwards compatible with IPv4. Doing so, we put our little bit, to help IPv6 come faster, since one minor problem which slows down the successor is that many programs are not developed with IPv6 in mind.

C Sockets. Changes to make

Remember C Socket Programming : Part 1 ? Lets see what changes have to be made, in order to make our applications IPv6 compatible. Take a quick look at the examples provided at Part 1.

[c light="true"]char ip[MAX_IPV4_SIZE]; //max would be lets say 111.111.111.111 = 3×4 ( nums ) + 3×1 ( dots ) = 15[/c]

We used char ip[15] in order to store the remote host IP at our example server. But since IPv6 uses a 128-bit representation we need more space to store an IPv6 address. For this reason we use :

[c light="true"]char ip[INET6_ADDRSTRLEN];[/c]

INET6_ADDRSTRLEN is define as 45 in header file <netinet/in.h> which is included by <netdb.h> which we include ourselves.

struct addrinfo.ai_family = AF_UNSPEC;

Back when we used only IPv4, the ai_family was always AF_INET. For IPv6 we would use AF_INET6, but this would break backwards-compability with IPv4. So we use AF_UNSPEC to declare that either IPv4 or IPv6 might be used, and this will be decided during the program runtime.

struct sockaddr_storage;

The struct used to storage IPv4 family information is sockaddr_in, but because IPv6 addresses require more space, there is struct sockaddr_in6 for such a case. But if we want to be compatible with both protocols, there is struct sockaddr_storage, which can hold information for both protocols!

Using helper / wrapper functions

When we called inet_ntop() in our server example, to convert the network byte-order address into human-readable format, we passed straight their_addr.sin_addr, asssuming the remote address is IPv4. But this wont be the case with IPv6 hosts, so we have to use a helper function, that will return either sin_addr or sin6_addr, depending on struct sockaddr_storage.ss_family.

Examples redefined

So, considering those changes to be made, here are the examples of C Socket Programming : Part 1 should look like.

[ server_ipv6.c ]

[c]

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define CON_NUM 10

void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char** argv) {
int sockfd, new_fd;
struct addrinfo hints, *servinfo;
struct sockaddr_storage their_addr;
socklen_t sin_size;
char *buff = (char*)malloc(1024);
char ip[INET6_ADDRSTRLEN];
int rc;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

if (argc != 2) {
printf("Usage : %s PORT\n", argv[0]);
return -1;
}

if ((rc = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
printf("Error at getaddrinfo() : %s\n", gai_strerror(rc));
return 1;
}

if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf("Error at socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
return 1;
}

if (bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
printf("Error at bind() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}

if (listen(sockfd, CON_NUM) == -1) {
printf("Error at listen() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
sin_size = sizeof their_addr;
while(1) {
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
printf("Error at accept() : %s\n", strerror(errno));
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr*)&their_addr), ip, sizeof ip);
printf("Got connection from %s\n", ip);
int j = 1;
while (1) {
j = recv(new_fd, buff, 1024, 0);
if ( j == 0 )
break;
if ( j == -1 ) {
printf("Error at recv() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
printf("Recieved : %s\n", buff);
}
}
freeaddrinfo(servinfo);
close(sockfd);
close(new_fd);
return 0;
}
[/c]

[ client.c ]

[c]

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = "hello!!";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf("Usage : %s HOSTNAME PORT\n", argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf("Error during getaddrinfo() : %s\n", gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(" Error during socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf("Error during connect() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf("Error during send() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf("Sent %d bytes.\n", bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}

[/c]

Resources : beej.us

Incoming Part 3 : Converting all this bunch of code, into pretty C++ Class!

As always, you can subscribe via RSS or follow wedevblog on twitter for the latest development posts!

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = “hello!!”;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf(“Usage : %s HOSTNAME PORT\n”, argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf(“Error during getaddrinfo() : %s\n”, gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(” Error during socket() : %s\n”, strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf(“Error during connect() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf(“Error during send() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf(“Sent %d bytes.\n”, bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = “hello!!”;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf(“Usage : %s HOSTNAME PORT\n”, argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf(“Error during getaddrinfo() : %s\n”, gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(” Error during socket() : %s\n”, strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf(“Error during connect() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf(“Error during send() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf(“Sent %d bytes.\n”, bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}

  • Share/Bookmark
Categories: dev Tags: , , , , ,

Gnome panel applet : Part 1

July 20th, 2009 Danny 6 comments

I was looking at my black gnome panel bar, and taking a look at all those little gadgets hooked on it! And i was wondering, could i make one too? So i looked it up, did some searches, encountered some headaches but well thanks to  a good tutorial i made it. So i thought i could try to pass to you this knowledge i gathered.

Generally, developing a widget / applet for a panel of  the Gnome graphical display manager is a mostly easy process. Such a widget, consists of two elements. It’s .server XML file, where many information about the widget are described. And the actual source code of the widget.

The source code is written in C / C++ or other languages by using the appropriate language bindings.
So, lets see how the “Hello World!” of a Gnome panel widget is like :)

I Will be using C++ ( its just C, but i use C++ in case i want to use string streams or the new operator, just a habbit, stick with C if you prefer. ) for the examples.
First of all, the .server file :

[ helloworld.server ]

[xml]<oaf_info>
<oaf_server iid="OAFIID:HelloWorld_Factory" type="exe"
location="/usr/lib/gnome-panel/helloworld">

<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/GenericFactory:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Hello World Factory"/>
<oaf_attribute name="description" type="string" value="its my own factory!"/>
</oaf_server>

<oaf_server iid="OAFIID:HelloWorld" type="factory"
location="OAFIID:HelloWorld_Factory">

<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
<item value="IDL:Bonobo/Control:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Hello World!!"/>
<oaf_attribute name="description" type="string" value="Thats my description!!"/>
<oaf_attribute name="panel:category" type="string" value="Amusements"/>
<oaf_attribute name="panel:icon" type="string" value="myicon.png"/>
</oaf_server>
</oaf_info>
[/xml]

Most of the .server XML code is the same for all apps. Notable lines are :

[xml light="true" wraplines="true"]<oaf_server iid="OAFIID:HelloWorld_Factory" type="exe" location="/usr/lib/gnome-panel/helloworld">[/xml]

Means that the unique IID of our applet will be “HelloWorld_Factory”, the name of the executable file will be named helloworld and located in folder “/usr/lib/gnome-panel”.

[xml light="true" wraplines="true"]<oaf_attribute name="name" type="string" value="Hello World!!"/>
<oaf_attribute name="description" type="string" value="Thats my description!!"/>[/xml]

“Hello World!” will be the name of the applet in the “Add to Panel…” menu and “Just a description…” will be the description of the applet displayed below its name. ( yeah you guessed right :) )

[xml light="true" wraplines="true"]<oaf_attribute name="panel:icon" type="string" value="myicon.png"/>[/xml]

This line specifies that the icon displayed for our applet in the “Add to panel…” menu will be named “myicon.png”. Note that it must be placed inside “/usr/share/pixmaps” directory.

The .server file has to be placed in the folder “/usr/lib/bonobo/servers/” so that Gnome will know which applications to “query” when you want to add a new applet on your panel. Now that we built the “describer” .server file, lets go onto the actual code of the applet :

[ helloworld.cpp ]

[c]
#include <string.h>
#include <panel-applet.h>
#include <gtk/gtklabel.h>

static gboolean
helloworld_applet_create (PanelApplet *applet,
const gchar *iid,
gpointer data)
{
GtkWidget *label;

if (strcmp (iid, "OAFIID:HelloWorld") != 0)
return FALSE;

label = gtk_label_new ("Hello World!!");
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}

PANEL_APPLET_BONOBO_FACTORY ("OAFIID:HelloWorld_Factory",
PANEL_TYPE_APPLET,
"The Hello World Applet",
"0",
helloworld_applet_create,
NULL);
[/c]

I am using GTK+ because its a bit more simple to me, but you can use gtkmm without any problem also.
As you can see, we include headers <panel-applet.h> which provides essential functions for the applet creation, and <gtk/gtklabel.h> , since our “Hello World!” example is just a label sitting on our Gnome Panel!

Lets take a look at the bottom first, where we call PANEL_APPLET_BONOBO_FACTORY() routine which takes as parameters :

  1. the OAFIID of the applet ( remember we typed it at the .server file )
  2. PANEL_TYPE_APPLET, which describes that our program will be a panel applet.
  3. The name which bonobo server will respond with when it gets queried for applets.
  4. The version of our creation.
  5. A callback function which will be called when the applet is added on the panel. ( helloworld_applet_create() in this example. )
  6. Data that we want to pass as arguments to the callback function, but we don’t need any, so we specify NULL.

Now consider the callback function helloworld_applet_create() like the constructor of our applet, our initiator. First of all, we define our variables ( GtkWidget *label ). It is important to check if bonobo called the right applet, by checking if the unique IID is the same with the one we specified in our .server file. After this point its just GTK+ programming, we just say label to show the appropriate text ( label = gtk_label_new (“Hello World”) ).

The space we are given in the panel ( PanelApplet *applet ) is like a GTK+ container, so we need to contain the label inside it by calling the gtk_container_add() function. In the end we show the applet and all its children ( the label in this case ) by calling gtk_widget_show_all().

Compiling

In order to compile our source file [ helloworld.cpp ] we need to tell g++ where to find the header files for the applets and the GTK+ library. Hopefully the program dpk-config can give us those directories or g++ include flags to be precise by using the command

[sourcecode language="plain" light="true"]pkg-config –cflags –libs libpanelapplet-2.0[/sourcecode]

So to combine this with the compilation, type

[sourcecode language="plain" light="true"]g++ $(pkg-config –cflags –libs libpanelapplet-2.0) -o helloworld helloworld.cpp[/sourcecode]

in your terminal.

By using $(pkg-config ….) we tell to the terminal to first execute the command included in the parentheses and include its output in the execution of the g++ command. Hopefully you have the package libpanelapplet-2.0-dev or the appropriate package required for your linux distribution installed.

Now you need to place the executable in “/usr/lib/gnome-panel/” directory and the helloworld.server file inside “/usr/lib/bonobo/servers/” if you haven’t already done it.
Right click on your Gnome Panel and select “Add to panel…”, choose “Hello World!” and voila!! A useless label sitting on your panel!

Result

Result

For any questions, post a comment, check links inside the post for more information on specific subjects.

Dont forget to follow wedevblog on twitter!

Incoming Part : 2, moving the “Hello World!” to the next step!

  • Share/Bookmark
Categories: dev Tags: , , , ,