DBus tutorial using the low-level API

In this post we will be studying DBus and how to use it from the so-called Low-level API. The DBus API documentation says “if you use this low-level API directly, you’re signing up for some pain.”

I don’t think so. Let’s start this journey.

Continue reading “DBus tutorial using the low-level API”

DBus tutorial using the low-level API

The performance of dynamic strings implementations

Let’s say you want to create a nice string abstract data type to use in your C code. You can end with a structure like this:

typedef struct mstring mstring;

struct mstring {
    int buflen;
    int len;
    char *buf;
};

mstring *mstring_new() {
    mstring *result;

    // insert memory allocation errors check here
    result = (mstring*)malloc(sizeof(struct mstring));
    result->len = 0;
    result->buflen = 128;
    result->buf = (char *)malloc(result->buflen);

    return result;
}

void mstring_append(mstring *dest, const char *src) {
    ...
}
  • the buflen field keeps track of the length of the allocated buffer;
  • the len field keeps track of the length of the string, so that you can know the string length in constant time;
  • the buf field keeps track of the memory address where the string is allocated. This field will be changed when you reallocate the string when the buffer is full.

It sound nice and you can also have manipulation functions that reallocate the string when necessary. They will be really useful! Let’s try:

mstring *m = mstring_new();

mstring_append(m, "Hi this is me! I'm ");
mstring_append(m, myNameHere);
printf("%s", m->buf);

mstring_delete(m); m=NULL;

This is nice indeed! But is really not that efficient from a memory point of view.
In your heap you will have:

  • The string descriptor (12 byte on a 32-bit architecture)
  • The string contents (variable length)

Your implementation of the holy tuple malloc and free must keep track of the string descriptor and of the strings contents, which can be (and will be) non-contiguous in memory.

You can do really better allocating the string descriptor directly before the string contents and having mstring_new return the address of the string contents instead of the string descriptor. Your strings will be C-compatible and more efficient.
Let’s try again:

typedef char *fstring;

struct fstring_header {
    int buflen;
    int len;
};

fstring fstring_new() {
    struct fstring_header *header;
    fstring result;

    header = (struct fstring_header*) malloc(128);
    header->buflen=128-sizeof(struct fstring_header);
    header->len=0;

    result = ((char*)header)+sizeof(struct fstring_header);
    result[0]=0;

    return result;
}

But now your fstring_append function can’t simply change the buf field when a buffer reallocation is needed. You must to reallocate the entire string, descriptor included.

fstring* fstring_append(fstring *dest, const char *src) {
    ....
}

So your code will change like this:

fstring *m = fstring_new();

m = fstring_append(m, "Hi this is me! I'm ");
m = fstring_append(m, myNameHere);
printf("%s", m);

fstring_delete(m); m=NULL;

You may say that this is premature optimization but wait! You saved:

  • one malloc
  • one free

and now the string descriptor is also attached to the string, and your cache will be happy. Really more efficient.
In my tests this string implementation is two times more efficient that the previous.

Want to try a really good dynamic string implementation? Try SDS. This is used in Redis.
You can also try my C all-purpose library here: CommonLib.

The performance of dynamic strings implementations

Iliad Framework, index page

In this post we will create a page to display the notes that we created with the project notes app. We will use the widget that we have created in the previous lesson to display the current user and we will create a form to search inside notes.

Creating the PnViewNotes widget

Let’s start by creating a new widget that will be the content of the new page:

ILWidget subclass: #PnViewNotes
    instanceVariableNames: 'searchstring'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'LeonardoBlog'

We created an instance variable, searchString, to remember the search string that will used to search inside the notes.

The rendering methods of the PnViewNotes widget

The interesting bits of this example are inside the rendering methods:

contents
!PnViewNotes methodsFor: 'building'!
    ^ [ :e | e h1 text:'Project notes'.
        e p text:'Use this application as a scratch pad. You can 
        attach to every page a series of tags to ease searching.'. 
        
        e build:self searchForm.
        e build:self searchResults ]

Let’s present the search form:

!PnViewNotes methodsFor: 'building'!
searchForm
    ^ [ :e | e form build:[ :form |
            form div class:'input-group'; build:[:row |
                row a class:'glyphicon glyphicon-plus input-group-addon'; action:[self addNewNote].
                row input class:'form-control'; beSubmitOnChange; 
                    attributeAt:'placeholder' put:'Search string'; 
                    action:[ :value | searchstring := value. self doSearch ].
                 ] ] ]

As you see we have used the BootstrapJs CSS declarations with the class: method of elements. When our element doesn’t support an attribute, like the placeholder attribute and the ILInputElement objects, we can manually place attributes with the methodattributeAt:put:`.

Another interesting bit is the beSubmitOnChange method, that will cause the ILInputElement to call the server every time the user changes the text field content, without waiting for the form to be submitted.

Every time the search string is modified we place the new content in the searchstring instance variable and we invoke the doSearch method to search inside the notes.

As we haven’t already implemented the notes DAO we delay the discussion of the doSearch method, that we implement like this:

!PnViewNotes methodsFor: 'actions'!
doSearch

The same thing happens with the addNewNote method:

!PnViewNotes methodsFor: 'actions'!
addNewNote

Until we haven’n implemented the PnNote object and its DAO we delay the implementation of the searchResults method:

!PnViewNotes methodsFor: 'building'!
searchResults
    ^ [ :e | ]

In this lesson we left many method unimplemented, but in the following one we implement the PnNote object and its DAO.

Iliad Framework, index page

Iliad Framework, a status widget for displaying the current user

In the previous post we completed the users registration form. Now we can use the login form.

To show the current user in the next pages we will implement a current user heading as a widget:

ILWidget subclass: #PnCurrentUserHeading
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'LeonardoBlog'

In the contents of this widget we will use the application method of the ILWidget class to access the current application and the current user:

!PnCurrentUserHeading methodsFor: 'building'!
contents
    ^ [ :e | 
    e div
        cssClass: 'navbar navbar-static-top bs-docs-nav';
        build: [ :header | 
                    header div
                        class: 'navbar-brand';
                        text: 'Project Notes for ' , self application currentuser email.
                    (header ul
                        cssClass: 'nav navbar-nav';
                        li)
                        build: [ :logout | 
                            logout a
                                text: 'Logout';
                                action: [ self logout ] ] ] ]

We also included a logout action that reset the current user and redirect the application to the login page:

!PnCurrentUserHeading methodsFor: 'actions'!
logout
    self application currentuser:nil.
    self redirectToLocal: 'login'.

We include this widget in the application class like we have done before with the login and the registration page:

ILApplication subclass: #LcBlogProjectNotes
    instanceVariableNames: 'loginWidget registrationWidget currentuser currentUserWidget'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'LeonardoBlog'

!LcBlogProjectNotes methodsFor: 'accessing'!
currentUserWidget
    ^ currentUserWidget ifNil: [ currentUserWidget := PnCurrentUserHeading new ]

Now we create a new notes controller:

!LcBlogProjectNotes methodsFor: 'controllers'!
notes
    ^ [ :e | e build:(self currentUserWidget). ]
Iliad Framework, a status widget for displaying the current user