Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Zoran Vasiljevic
On Fri, 1 Feb 2019 11:50:58 -0500
Andrew Piskorski  wrote:

> work around the "Nsvs only store strings" limitation

This "limitation" is rather the only generic and 
safe option! And it is pretty trivial in implementation.

To see the other possibility, look in the tsv in the
threading extension. It is much more complicated but allows
one to "share" objects between threads w/o constant to/from
string conversion. But it is black magic (rather complex)
and limited (by the very nature of Tcl_Objs) to some well
known simple object types.

Cheers,
Zoran




___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] Ns_VarGet vs. NsTclNsvGetObjCmd

2019-02-01 Thread Zoran Vasiljevic
On Fri, 1 Feb 2019 11:15:46 -0500
Andrew Piskorski  wrote:

> since I'm not using virtual servers anyway, how do I say 
> "all of them, process-wide"?

You can't. The nsv buckets are stored on per-server basis. 
Naviserver may run a number of virtual servers. You declare
all this in the configuration file. 
See "ns/servers" part in your configuration file. 

It is your module that, when loaded in the Naviserver,
gets the name of the current server it is loaded into.

To be loaded as extension, your code needs to provide
Ns_ModuleInit() call that gets called by the module
loader when a virtual server is getting initialized.

The system passes the name of the server and name of
the module to your Ns_ModuleInt(). You need to store
it somewhere for later use. 

HTH,
ZOran



___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Andrew Piskorski
On Fri, Feb 01, 2019 at 05:28:50PM +0100, Zoran Vasiljevic wrote:

> OTOH, if you use ns:addr object, you need not take care about
> locking and all the other trivia at all. It is the "rest" of 
> the system that needs to do that. 

> > Some of the stuff in "nsd/tclobj.c" seems be primarily concerned with
> > the "address object type" (IP addresses?), but I get the sense that

> It's (memory-)addresses == pointers.

Ah!  And you've already written the code to correctly convert between
the pointer and string representations, so the ns:addr object approach
is also a way to work around the "Nsvs only store strings" limitation.

Thanks you, Zoran.  I'm not sure which way I'll go in my implementation,
but the choices available to me are making more sense now.

-- 
Andrew Piskorski 


___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Zoran Vasiljevic
On Fri, 1 Feb 2019 10:57:00 -0500
Andrew Piskorski  wrote:

> What if you don't care much about Tcl objects?  A C pointer is already
> easily shareable across threads (you just need the proper mutex
> locking when using it), the trick is finding it again using some
> handle from Tcl.  For simplicity, should I just completely ignore the
> whole Tcl_Obj machinery when doing that?

Of course. You can always use a lock, hash-table and
key your pointers, passing the key to the Tcl.
But you asked for some other way to do it :-)

> 
> Or SHOULD I (always?) make my handle into a Tcl_Obj?  If so, can you
> go into a bit more detail on WHY that's a better approach?  Even
> despite the fact that this Tcl_Obj thing is now more difficult to
> share across threads?

By having a Tcl object that contains ptr rep, you can
safely toss it arround Tcl as it will be a "natural" Tcl
thing. You can treat it everywhere as a regular Tcl object.
Whereas if you opt for the above approach, you need to "know"
what that key points to. If you are only consumer of that key
it is pretty OK to do it. But if you are passing ptr's arround
the "unknown" code you might be better with object. This is why
we did the ns:addr object, so that we do not have to care.

It is really the same thing but other way around.

> 
> If I take an ordinary sort of Tcl string or integer and hand it to my
> C code, that works fine as the key for an nsv or Tcl_HashTable lookup.
> Of course, the code doesn't "know" that that particular string is
> supposed to be a handle, but there's nothing stopping me from simply
> using it as one in the C code, and throwing an error if I can't find a
> hash entry for it.

Exactly.

> 
> I suspect that the above is NOT the recommended approach, but I don't
> fully understand why.  It seems "simpler" to me...  But maybe that's
> only because I don't yet understand the Tcl_Obj integration approach,
> and what benefits it provides.

It is "simpler" because you are used to it. But in essence, you need
to make a shared hash table, invent a key for your pointers and make 
sure all is always properly locked. So it isn't per-se simpler.
It is still a devil, but that devil isn't that black because you
already know it :-)

OTOH, if you use ns:addr object, you need not take care about
locking and all the other trivia at all. It is the "rest" of 
the system that needs to do that. 

> Hm, that has Ns_TclSetTwoPtrValue(), Ns_TclGetOpaqueFromObj(), and
> other black magic (or so it seems to me).  Are there docs on these C
> APIs anywhere?

No. But it is really trivial. If you want to wrap a ptr into
the ns:addr object you can do:

  Tcl_Obj *myObj = Tcl_NewObj();
  char *myType = "at-ptr"; /* Name it as you want */
  MyDataStruct *myStruct = &MyGlobalStruct;

  Ns_TclSetAddrObj(myObj, myType, (void*)myStruct);

Now you can pass the myObj to Tcl (put it in result,
bury it in some list, store it in nsv array etc.pp.). 
Your code may later access the address/ptr value:

  Tcl_Obj *myObj = objv[1]; /* For example */
  MyDataStruct *myStruct;
  Ns_TclGetOpaqueFromObj(myObj, myType, (void**)&myStruct);

so now you have (or don't if GetOpaque retuns TCL_ERROR)
your initial *myStruct value.

> 
> Some of the stuff in "nsd/tclobj.c" seems be primarily concerned with
> the "address object type" (IP addresses?), but I get the sense that
> much of that code is much more general purpose than that.  I see that
> "nsd/tcltime.c" uses the tclobj.c functions to implement an Ns_Time
> Tcl_Obj type, but I definitely don't understand how or why yet!
> 

It's (memory-)addresses == pointers.

HTH,
Zoran




___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] Ns_VarGet vs. NsTclNsvGetObjCmd

2019-02-01 Thread Andrew Piskorski
On Fri, Feb 01, 2019 at 04:25:20PM +0100, Zoran Vasiljevic wrote:

> > I'm a little confused by (e.g.) Ns_VarGet(), though.  Why is its first
> > arg a string for the "server"?  What does that mean, and where am I
> > supposed to get it from?
> 
> This is the identification of the Naviserver's virtual server
> that is implicitly "known" to the Tcl code. The nsv_XXX is 
> thus bound to a virtual server since your Tcl code executes
> within a specific virtual server. But on the C-level you need
> to specify the virtual server explicitly because your C code
> may operate for all known virtual servers or just bunch of them.

Ok.  But where do I get the server string from, in C?  Or since I'm not
using virtual servers anyway, how do I say "all of them, process-wide"?

-- 
Andrew Piskorski 


___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Andrew Piskorski
On Fri, Feb 01, 2019 at 11:44:45AM +0100, Zoran Vasiljevic wrote:

> The only safe way to share data between threads
> in Tcl is over strings. One can go to some extent
> and try making Tcl objects shareable but for that
> you need to know the object internals which is a 
> great PITA and does not always work well, except for
> a limited set of object types.

What if you don't care much about Tcl objects?  A C pointer is already
easily shareable across threads (you just need the proper mutex locking
when using it), the trick is finding it again using some handle from
Tcl.  For simplicity, should I just completely ignore the whole Tcl_Obj
machinery when doing that?

Or SHOULD I (always?) make my handle into a Tcl_Obj?  If so, can you
go into a bit more detail on WHY that's a better approach?  Even
despite the fact that this Tcl_Obj thing is now more difficult to
share across threads?

If I take an ordinary sort of Tcl string or integer and hand it to my
C code, that works fine as the key for an nsv or Tcl_HashTable lookup.
Of course, the code doesn't "know" that that particular string is
supposed to be a handle, but there's nothing stopping me from simply
using it as one in the C code, and throwing an error if I can't find a
hash entry for it.

I suspect that the above is NOT the recommended approach, but I don't
fully understand why.  It seems "simpler" to me...  But maybe that's
only because I don't yet understand the Tcl_Obj integration approach,
and what benefits it provides.

On Fri, Feb 01, 2019 at 10:29:47AM +0100, Zoran Vasiljevic wrote:
> You might want to look into:
> 
>nsd/tclobj.c

Hm, that has Ns_TclSetTwoPtrValue(), Ns_TclGetOpaqueFromObj(), and
other black magic (or so it seems to me).  Are there docs on these C
APIs anywhere?

Some of the stuff in "nsd/tclobj.c" seems be primarily concerned with
the "address object type" (IP addresses?), but I get the sense that
much of that code is much more general purpose than that.  I see that
"nsd/tcltime.c" uses the tclobj.c functions to implement an Ns_Time
Tcl_Obj type, but I definitely don't understand how or why yet!

-- 
Andrew Piskorski 


___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] Ns_VarGet vs. NsTclNsvGetObjCmd

2019-02-01 Thread Zoran Vasiljevic
On Fri, 1 Feb 2019 09:59:09 -0500
Andrew Piskorski  wrote:

> So they do the exact same thing, and are completely interoperable?
> Meaning I can have C and Tcl talk to each other via Ns_Var* in C and
> nsv_* in Tcl?  Great!

Yes.

> 
> I'm a little confused by (e.g.) Ns_VarGet(), though.  Why is its first
> arg a string for the "server"?  What does that mean, and where am I
> supposed to get it from?

This is the identification of the Naviserver's virtual server
that is implicitly "known" to the Tcl code. The nsv_XXX is 
thus bound to a virtual server since your Tcl code executes
within a specific virtual server. But on the C-level you need
to specify the virtual server explicitly because your C code
may operate for all known virtual servers or just bunch of them.

> 
> Also, why are NsTclNsvGetObjCmd() and Ns_VarGet()
> implemented independently, rather than NsTclNsvGetObjCmd() calling
> Ns_VarGet()? I assume there's some good reason for this, but I'd like
> to understand what it is...

Well, simplicity, that is. In essence, one could have done that
but it would be more complicated. The former operates mainly
with Tcl objects from within one Tcl script whereas the latter is 
mainly (supposed to be) used from C code that has no relation to
any Tcl interp/script. If you compare the guts of both calls you will
see something like LockArray/CreateHashEntry which is what "counts".
Everything else is glue.

HTH,
Zoran




___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] Ns_VarGet vs. NsTclNsvGetObjCmd

2019-02-01 Thread Andrew Piskorski
On Fri, Feb 01, 2019 at 10:22:46AM +0100, Zoran Vasiljevic wrote:
> Andrew Piskorski  wrote:
> 
> > I know that the Tcl nsv_get command is implemented by
> > NsTclNsvGetObjCmd(). But in the NaviServer C code, what is
> > Ns_VarGet() for?  I don't see it used anywhere.  Is Ns_VarGet() a C
> > interface to exact same nsv_get functionality, or is it for something
> > completely different?
> 
> The Ns_VarXXX is a programatic interface (from C)
> to the nsv (Naviserver Shared Variables) storage.

So they do the exact same thing, and are completely interoperable?
Meaning I can have C and Tcl talk to each other via Ns_Var* in C and
nsv_* in Tcl?  Great!

I'm a little confused by (e.g.) Ns_VarGet(), though.  Why is its first
arg a string for the "server"?  What does that mean, and where am I
supposed to get it from?

Also, why are NsTclNsvGetObjCmd() and Ns_VarGet() implemented
independently, rather than NsTclNsvGetObjCmd() calling Ns_VarGet()?
I assume there's some good reason for this, but I'd like to understand
what it is...

-- 
Andrew Piskorski 


___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Zoran Vasiljevic
On Thu, 31 Jan 2019 15:46:59 -0500
Andrew Piskorski  wrote:

>  And I already know how to call
> NsTclNsvGetObjCmd() etc. from C.  But the Nsv functions all operate
> ONLY on strings...

Oh yes, never use NsXXX calls in your code
as these are not exported and may change anytime. 
Always use Ns_XXX instead.

The only safe way to share data between threads
in Tcl is over strings. One can go to some extent
and try making Tcl objects shareable but for that
you need to know the object internals which is a 
great PITA and does not always work well, except for
a limited set of object types.

Cheers,
Zoran
 




___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] store C pointers in Nsv vs. Tcl_HashTable?

2019-02-01 Thread Zoran Vasiljevic
On Thu, 31 Jan 2019 15:46:59 -0500
Andrew Piskorski  wrote:

> In general, what's the recommended way for Tcl and/or NaviServer
> programmers to allocate handles to C-level pointers, and then access
> those handles and pointers from more than one Tcl thread?  Can anyone
> point me to examples of code doing it the right way?

You might want to look into:

   nsd/tclobj.c

Cheers,
Zoran



___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


Re: [naviserver-devel] Ns_VarGet vs. NsTclNsvGetObjCmd

2019-02-01 Thread Zoran Vasiljevic
On Thu, 31 Jan 2019 14:48:11 -0500
Andrew Piskorski  wrote:

> I know that the Tcl nsv_get command is implemented by
> NsTclNsvGetObjCmd(). But in the NaviServer C code, what is
> Ns_VarGet() for?  I don't see it used anywhere.  Is Ns_VarGet() a C
> interface to exact same nsv_get functionality, or is it for something
> completely different?

The Ns_VarXXX is a programatic interface (from C)
to the nsv (Naviserver Shared Variables) storage.

Cheers,
Zoran



___
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel