|Anonymous | Login | Signup for a new account||2014-04-23 21:49 CEST|
|Main | My View | View Issues | Change Log | Roadmap|
|View Issue Details|
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0005436||OCaml||OCaml general||public||2011-12-20 13:15||2013-08-31 12:48|
|Priority||normal||Severity||minor||Reproducibility||have not tried|
|Target Version||Fixed in Version||3.13.0+dev|
|Summary||0005436: Clarify (or fix) the semantics of Oo.id|
|Description||It should be clarified how Oo.id behaves in the following cases:|
- Multi-threaded program: is it guaranteed that two different threads cannot create objects with the same id (I think so).
- Serialized objects: currently, unmarshaling does not assign fresh ids to objects. It is thus possible to have two different objects in the same run of the program. Shouldn't unmarshaling reassign ids instead? One could then make clear in the documentation that Oo.id (and thus, generic hash/comparison) is not stable across "marshaling" boundaries, but at least one would keep the uniqueness property.
|Tags||No tags attached.|
For the second point, this is oops! : indeed ids should be fresh upon unmarshaling.
It seems that I forgot to implement it (there is a subtle interaction between C code
and ocaml code).
For the first point, we have to check the code.
Maybe it would be better to move the id handling to the C side, since it would avoid the risk of races too.
For point 1, ids are guaranteed to be different in different threads:
CamlinternalOO.set_id only reads and assigns to records fields, so no thread switch can occur during its execution.
(At least I believe so. Reading the code in interp.c and systhreads doesn't help me much about
when thread switches can occur.)
For point 2, indeed the behavior was incorrect, and ids were not updated when unmarshaling.
This is now fixed in revision 11930.
One must be careful however that ids cached inside data structures lose their meaning as a result.
|I've added some words of warning the documentation for Oo.id.|
|I agree with Jacques that we should probably move the generation of fresh IDs to C code, to simplify unmarshaling and to provide clear atomicity guarantees.|
Would it be possible to also expose the unique id generation as a function in pervasives or Sys ?
That's a useful function beyond ids for objects. I use the id of empty objects as thread safe runtime unique ids in more than one program to implement the keys of type safe heterogenous dictionaries (on Alan's F. suggestion btw. ).
let ruid () = Oo.id (object end)
This would avoid linking against Oo in these programs.
 http://alan.petitepomme.net/cwn/2010.02.09.html#1 [^]
My fix in revision 11930 keeps the id generation in CamlinternalOO, just exporting the current id through Callback.register_value.
The code is:
let set_id o id =
let id0 = !id in
Array.unsafe_set (Obj.magic o : int array) 1 id0;
id := id0 + 1
Is there any risk of race?
I thought that thread switch could only occur at function calls.
Before doing that, I tried a version with id generation on the C side, but I was afraid that this would make object creation slower. If you think this wouldn't have any impact, I'll revert to that solution.
You can find the patch in experimental/garrigue/caml_set_oid.diffs.
By the way, if the code generating ids in CamlinternalOO is already safe, there is clearly no need to include CamlinternalOO to do that: you just have to duplicate the above 4 lines.
> By the way, if the code generating ids in CamlinternalOO is already safe, there is clearly no need to
> include CamlinternalOO to do that: you just have to duplicate the above 4 lines.
Oh right. You mean that what I thought was not thread-safe :
let create =
let c = ref min_int in
fun () ->
let id = !c in
incr c; if id > !c then assert false (* too many ids *) else id
is in fact thread-safe because no allocation occurs between let id = !c, incr c and the conditional ?
|Still this would rely on an implementation detail, I'd prefer if something was given to me by the runtime system.|
|2011-12-20 13:15||frisch||New Issue|
|2011-12-20 13:55||garrigue||Assigned To||=> garrigue|
|2011-12-20 13:55||garrigue||Status||new => assigned|
|2011-12-20 13:58||garrigue||Note Added: 0006411|
|2011-12-20 13:58||garrigue||Status||assigned => acknowledged|
|2011-12-22 08:51||garrigue||Note Added: 0006482|
|2011-12-22 08:51||garrigue||Status||acknowledged => resolved|
|2011-12-22 08:51||garrigue||Fixed in Version||=> 3.13.0+dev|
|2011-12-22 08:51||garrigue||Resolution||open => fixed|
|2011-12-22 12:47||frisch||Note Added: 0006503|
|2011-12-28 11:34||xleroy||Note Added: 0006546|
|2011-12-28 12:55||dbuenzli||Note Added: 0006549|
|2011-12-29 07:52||garrigue||Note Added: 0006551|
|2011-12-29 12:07||dbuenzli||Note Added: 0006552|
|2012-03-24 21:47||dbuenzli||Note Added: 0007150|
|2013-08-31 12:48||xleroy||Status||resolved => closed|
|Copyright © 2000 - 2011 MantisBT Group|