lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Thanks Sean,

I've converted to pointer to pointer and it's working fine.

> Some random comments:  you don't need checkSelFIFO()---luaL_checkudata() will do what you want.

It's only to embbed type checking with luaL_argcheck().
As per my reading, luaL_checkudata() only returns a NULL in case of check failure, isn't it ?
(it would be more efficient to be an inline function ... and it will be).

> Second, DO NOT USE assert() TO CHECK THE RETURN CODE
> FOR FUNCTIONS!

It is only by laziness :) I have done that for very small allocations: if they fail, in any case, the application is close to crash facing a severe starvation of resources.

Thanks again.

Laurent

Le Jeudi 22 juin 2017 1h33, Sean Conner <sean@conman.org> a écrit :


It was thus said that the Great Laurent FAILLIE once stated:
> Hi,
> I'm building a multi-threaded application and all threads carry their own
> stat.Now, I have to create an object to share data among those stats,
> named SelFIFO : this object is NEVER subject to be collected, mutex are
> handled at C side and slaves only get a C pointer to userdata.

  By "stat" do you mean "Lua state"?

> My concern is "how can I insert this pointer to slave stats ?".
> So, in the main thread, this object is created like that :
> struct SelFIFO *q = (struct SelFIFO *)lua_newuserdata(L, sizeof(struct SelFIFO));
> assert(q);
> luaL_getmetatable(L, "SelFIFO");
> lua_setmetatable(L, -2);
> ...
> but, in the slave thread, I got only 'q' pointer.How can I push it in slave's stat ?How can I associate a "SelFIFO" to it ?
> Thanks
> Laurent
> ps: full source code is https://github.com/destroyedlolo/Selene/blob/master/src/SelFIFO.c

  Some random comments:  you don't need checkSelFIFO()---luaL_checkudata()
will do what you want.  Second, DO NOT USE assert() TO CHECK THE RETURN CODE
FOR FUNCTIONS!  In particular, this is wrong:

    assert(q->name = strdup(n));

  Unless you are coding in C++ (and you are not), you do not need to cast
the return code from lua_newuserdata() or any other function that returns a
void *.  In fact, you should NOT do that as it can hide bugs.

  The easiest way to get what you want is to change sff_create():

    static int sff_create(lua_State *L)
    {
      const char      *n = luaL_checkstring(L,1);
      char            *copy;
      struct SelFIFO **q = lua_newuserdata(L,sizeof(struct SelFIFO **));
   
      /*-------------------------------------
      ; copy the string from Lua and bail if we can't copy it
      ;------------------------------------------------------*/
   
      copy = strdup(n);
   
      if (copy == NULL)
      {
        lua_pushnil(L);
        return 1;
      }
   
      /*------------------------------------------------
      ; allocate memory for the SelFIFO.  Bail if we can't create it.
      ;-------------------------------------------------------------*/
   
      *q = calloc(1,sizeof(struct SelFIFO));
   
      if (*q == NULL)
      {
        lua_pushnil(L);
        return 1;
      }
   
      pthread_mutex_init(&q->mutex,NULL);
   
      q->h      = hash(n);
      q->name  = copy;
      q->first  = NULL;
      q->last  = NULL;
      q->next  = firstFifo;
      firstFifo = q;

      return 1;
    }

  Then sff_find() becomes:

    static int sff_find(lua_State *L)
    {
      const char *n = luaL_checkstring(L,1);
      int        h = hash(n);
     
      for (struct SelFIFO *p = firstFifo ; p ; p = p->next)
      {
        if ((h == p->h) && (strcmp(n,p->name) == 0))
        {
          struct SelFIFO **q = lua_newuserdata(L,sizeof(struct SelFIFO **));

          *q = p;

          return 1;
        }
      }
   
      return 0;
    }
   
  By using a pointer-to-a-pointer, it's easier to push the FIFO into other
states.

  -spc (Hope this helps some)