On Thursday 10 January 2008 09:58:10 Linus Torvalds wrote:
> On Thu, 10 Jan 2008, Rusty Russell wrote:
> > I'd have to read his original statement, but eventfd doesn't build up
> > state, so I think it qualifies.
>
> How about you guys battle it out by giving an example program usign the
> interface?

Nice idea.

> And *simplicity* of the end result really does matter. If it's not simple
> to use, people won't use it.

Completely agreed, but async is always more complex than sync.  

eg. your malloc()-and-overwrite trick here assumes it's serial, similarly 
stack vars.  Even before anything's happened we've massively increased the 
number of mallocs :(  Maybe someone else can see a neater way?

Below is an async-ready version (I've assumed you still want each dir grouped 
together).  It's already slower (best 0m3.842s vs best 0m3.659s):

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static void find(const char *base, int baselen);

struct result
{
        struct result *next;
        struct stat st;
        unsigned int namelen;
        char name[];
};

static struct result *new_result(const char *base, int baselen,
                                 const char *sub, int sublen)
{
        struct result *r;

        r = malloc(sizeof(*r) + baselen + sublen + 2);
        memcpy(r->name, base, baselen);
        r->name[baselen] = '/';
        memcpy(r->name + baselen + 1, sub, sublen+1);
        r->namelen = baselen + sublen + 1;
        
        return r;
}

static void process(struct result *r, struct result **dirs)
{
        printf("%8lu %s\n", r->st.st_size, r->name);
        if (S_ISDIR(r->st.st_mode)) {
                r->next = *dirs;
                *dirs = r;
        } else 
                free(r);
}

/* -1 = fail, 0 = success, 1 = in progress. */
static int handle_async(struct result *r)
{
        /* Ours is sync. */
        return lstat(r->name, &r->st);
}

static void process_pending(struct result *pending, struct result **dirs)
{
        /* Since we're sync, pending will be NULL.  Otherwise call
        pending as they complete. */
}

static void find(const char *base, int baselen)
{
        DIR *dir;
        struct result *r, *pending = NULL, *dirs = NULL;

        dir = opendir(base);
        if (dir) {
                struct dirent *de;
                while ((de = readdir(dir)) != NULL) {
                        const char *p = de->d_name;
                        int len = strlen(p);
                        if (p[0] == '.') {
                                if (len == 1)
                                        continue;
                                if (len == 2 && p[1] == '.')
                                        continue;
                        }
                        r = new_result(base, baselen, p, len);
                        switch (handle_async(r)) {
                        case 0:
                                process(r, &dirs);
                                break;
                        case -1:
                                free(r);
                                break;
                        case 1:
                                r->next = pending;
                                pending = r;
                        }
                }
                closedir(dir);
                process_pending(pending, &dirs);
                while (dirs) {
                        find(dirs->name, dirs->namelen);
                        r = dirs;
                        dirs = dirs->next;
                        free(r);
                }
        }
}

int main(int argc, char **argv)
{
        find(".",1);
        return 0;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to