~ubuntu-branches/ubuntu/trusty/ocamlnet/trusty

« back to all changes in this revision

Viewing changes to doc/html-main/Netmcore_tut.html

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-12-23 21:53:27 UTC
  • mfrom: (18.2.11 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131223215327-ezc6kxzldh4ki71o
Tags: 3.7.3-3build2
Rebuild for ocaml-4.01.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
6
6
<link rel="Start" href="index.html">
7
7
<link rel="previous" href="Netmcore_process.html">
8
 
<link rel="next" href="Netplex_types.html">
 
8
<link rel="next" href="Netmcore_basics.html">
9
9
<link rel="Up" href="index.html">
10
10
<link title="Index of types" rel=Appendix href="index_types.html">
11
11
<link title="Index of exceptions" rel=Appendix href="index_exceptions.html">
81
81
<link title="Netmcore_hashtbl" rel="Chapter" href="Netmcore_hashtbl.html">
82
82
<link title="Netmcore_process" rel="Chapter" href="Netmcore_process.html">
83
83
<link title="Netmcore_tut" rel="Chapter" href="Netmcore_tut.html">
 
84
<link title="Netmcore_basics" rel="Chapter" href="Netmcore_basics.html">
84
85
<link title="Netplex_types" rel="Chapter" href="Netplex_types.html">
85
86
<link title="Netplex_mp" rel="Chapter" href="Netplex_mp.html">
86
87
<link title="Netplex_mt" rel="Chapter" href="Netplex_mt.html">
98
99
<link title="Netplex_sharedvar" rel="Chapter" href="Netplex_sharedvar.html">
99
100
<link title="Netplex_mutex" rel="Chapter" href="Netplex_mutex.html">
100
101
<link title="Netplex_encap" rel="Chapter" href="Netplex_encap.html">
 
102
<link title="Netplex_mbox" rel="Chapter" href="Netplex_mbox.html">
101
103
<link title="Netplex_intro" rel="Chapter" href="Netplex_intro.html">
102
104
<link title="Netplex_advanced" rel="Chapter" href="Netplex_advanced.html">
103
105
<link title="Netplex_admin" rel="Chapter" href="Netplex_admin.html">
122
124
<link title="Netaccel_link" rel="Chapter" href="Netaccel_link.html">
123
125
<link title="Nethtml" rel="Chapter" href="Nethtml.html">
124
126
<link title="Netstring_str" rel="Chapter" href="Netstring_str.html">
125
 
<link title="Netstring_pcre" rel="Chapter" href="Netstring_pcre.html">
126
127
<link title="Netmappings" rel="Chapter" href="Netmappings.html">
127
128
<link title="Netaux" rel="Chapter" href="Netaux.html">
128
129
<link title="Nethttp" rel="Chapter" href="Nethttp.html">
136
137
<link title="Xdr_mstring" rel="Chapter" href="Xdr_mstring.html">
137
138
<link title="Xdr" rel="Chapter" href="Xdr.html">
138
139
<link title="Netcompression" rel="Chapter" href="Netcompression.html">
 
140
<link title="Netunichar" rel="Chapter" href="Netunichar.html">
139
141
<link title="Netchannels_tut" rel="Chapter" href="Netchannels_tut.html">
140
142
<link title="Netmime_tut" rel="Chapter" href="Netmime_tut.html">
141
143
<link title="Netsendmail_tut" rel="Chapter" href="Netsendmail_tut.html">
142
144
<link title="Netulex_tut" rel="Chapter" href="Netulex_tut.html">
143
145
<link title="Neturl_tut" rel="Chapter" href="Neturl_tut.html">
 
146
<link title="Netstring_pcre" rel="Chapter" href="Netstring_pcre.html">
144
147
<link title="Netsys" rel="Chapter" href="Netsys.html">
145
148
<link title="Netsys_posix" rel="Chapter" href="Netsys_posix.html">
146
149
<link title="Netsys_pollset" rel="Chapter" href="Netsys_pollset.html">
157
160
<link title="Netsys_types" rel="Chapter" href="Netsys_types.html">
158
161
<link title="Netsys_mem" rel="Chapter" href="Netsys_mem.html">
159
162
<link title="Netsys_tmp" rel="Chapter" href="Netsys_tmp.html">
 
163
<link title="Netsys_sem" rel="Chapter" href="Netsys_sem.html">
 
164
<link title="Netsys_pmanage" rel="Chapter" href="Netsys_pmanage.html">
160
165
<link title="Netgzip" rel="Chapter" href="Netgzip.html">
161
166
<link title="Netpop" rel="Chapter" href="Netpop.html">
162
167
<link title="Rpc_auth_dh" rel="Chapter" href="Rpc_auth_dh.html">
191
196
<link title="Intro" rel="Chapter" href="Intro.html">
192
197
<link title="Platform" rel="Chapter" href="Platform.html">
193
198
<link title="Foreword" rel="Chapter" href="Foreword.html">
194
 
<link title="Ipv6" rel="Chapter" href="Ipv6.html"><link title="Netmulticore Tutorial" rel="Section" href="#1_NetmulticoreTutorial">
 
199
<link title="Ipv6" rel="Chapter" href="Ipv6.html">
 
200
<link title="Regexp" rel="Chapter" href="Regexp.html"><link title="Netmulticore Tutorial" rel="Section" href="#1_NetmulticoreTutorial">
195
201
<link title="Design" rel="Subsection" href="#design">
196
202
<link title="How to start processes" rel="Subsection" href="#start_procs">
197
203
<link title="How to use Camlboxes for passing messages" rel="Subsection" href="#camlboxes">
208
214
<title>Ocamlnet 3 Reference Manual : Netmcore_tut</title>
209
215
</head>
210
216
<body>
211
 
<div class="navbar"><a href="Netmcore_process.html">Previous</a>
212
 
&nbsp;<a href="index.html">Up</a>
213
 
&nbsp;<a href="Netplex_types.html">Next</a>
 
217
<div class="navbar"><a class="pre" href="Netmcore_process.html" title="Netmcore_process">Previous</a>
 
218
&nbsp;<a class="up" href="index.html" title="Index">Up</a>
 
219
&nbsp;<a class="post" href="Netmcore_basics.html" title="Netmcore_basics">Next</a>
214
220
</div>
215
 
<center><h1>Netmcore_tut</h1></center>
216
 
<br>
217
 
<br>
218
 
<span id="1_NetmulticoreTutorial"><h1>Netmulticore Tutorial</h1></span>
 
221
<h1>Netmcore_tut</h1>
 
222
<br>
 
223
<h1 id="1_NetmulticoreTutorial">Netmulticore Tutorial</h1>
219
224
<p>
220
225
 
221
226
<b>Contents</b>
244
249
multicore CPU's.
245
250
<p>
246
251
 
 
252
<div class="remark">
 
253
Readers are encouraged to first have a look at <a href="Netmcore_basics.html"><code class="code">Netmcore_basics</code></a>,
 
254
which is more fundamental and doesn't use unsafe language features.
 
255
</div>
 
256
<p>
 
257
 
 
258
<div class="remark">
 
259
<b>Since OCaml-4.01:</b> This OCaml version changed the semantics of the
 
260
built-in primitives <code class="code">caml_modify</code> and <code class="code">caml_initialize</code>. Essentially,
 
261
it is no longer possible to modify OCaml values residing outside the
 
262
regular OCaml heap. As we do this inside Netmulticore, this change affects
 
263
this library. Fortunately, there is a workaround on systems supporting
 
264
weak symbols (all ELF systems and OS X): Here, <code class="code">caml_modify</code> and
 
265
<code class="code">caml_initialize</code> are overridden by Netmulticore so that they are again
 
266
compatible. Note that this is a global modification of the runtime
 
267
system!
 
268
<p>
 
269
 
 
270
Future versions of Ocamlnet may solve this problem differently.
 
271
</div>
 
272
<p>
 
273
 
247
274
The approach of Netmulticore is to spawn subprocesses acting in the
248
275
role of worker threads. Processes are separated from each other, and
249
276
hence there is normally no direct way of getting into interaction.
298
325
and is in no way different.
299
326
<p>
300
327
 
301
 
<span id="design"><h2>Design</h2></span>
 
328
<h2 id="design">Design</h2>
302
329
<p>
303
330
 
304
 
<span id="3_Theprocesshierarchy"><h3>The process hierarchy</h3></span>
 
331
<h3 id="3_Theprocesshierarchy">The process hierarchy</h3>
305
332
<p>
306
333
 
307
334
When processes start other processes, the Unix system design defines a
340
367
user code requests the creation.
341
368
<p>
342
369
 
343
 
<span id="3_Resources"><h3>Resources</h3></span>
 
370
<h3 id="3_Resources">Resources</h3>
344
371
<p>
345
372
 
346
373
Netmulticore manages not only processes but also other kinds of
365
392
any worker, it is automatically deleted.
366
393
<p>
367
394
 
368
 
<span id="3_Memorypools"><h3>Memory pools</h3></span>
 
395
Since Ocamlnet-3.6, the deletion procedure has been substantially
 
396
improved. Now, a list of the alive resources is not only kept in
 
397
memory, but also written to a file "netplex.pmanage". This allows it
 
398
to delete the resources after the program has crashed or terminated
 
399
somehow abnormally. This is automatically done when the program is
 
400
restarted, or by the user running the <code class="code">netplex-admin</code> utility with
 
401
option <code class="code">-unlink</code>. The background for this is that the mentioned
 
402
resources have kernel persistency, and continue to exist when the
 
403
program is finished.
 
404
<p>
 
405
 
 
406
<h3 id="3_Memorypools">Memory pools</h3>
369
407
<p>
370
408
 
371
409
For setting up shared heaps as explained below, we especially need
413
451
memory pieces from a single <a href="Netmcore_mempool.html"><code class="code">Netmcore_mempool</code></a>.
414
452
<p>
415
453
 
416
 
<span id="3_Sharedheaps"><h3>Shared heaps</h3></span>
 
454
<h3 id="3_Sharedheaps">Shared heaps</h3>
417
455
<p>
418
456
 
419
457
What is now a heap, or better <i>shared heap</i>? It is just a memory
441
479
and hash tables.
442
480
<p>
443
481
 
444
 
<span id="3_Camlboxes"><h3>Camlboxes</h3></span>
 
482
<h3 id="3_Camlboxes">Camlboxes</h3>
445
483
<p>
446
484
 
447
485
For fast notification between processes, Netmulticore uses Camlboxes.
471
509
but really Ocaml values, relocated to the receiver's address.
472
510
<p>
473
511
 
474
 
<span id="3_Synchronization"><h3>Synchronization</h3></span>
 
512
<h3 id="3_Synchronization">Synchronization</h3>
475
513
<p>
476
514
 
477
515
Netmulticore provides these synchronization primitives:
503
541
the user can put these primitives.
504
542
<p>
505
543
 
506
 
<span id="start_procs"><h2>How to start processes</h2></span>
 
544
<h2 id="start_procs">How to start processes</h2>
507
545
<p>
508
546
 
509
547
For starting processes, there are actually two API's: the slightly
515
553
Before a process can be started, it needs to be defined:
516
554
<p>
517
555
 
518
 
<pre><code class="code">let process_fork, process_join =
 
556
<pre class="codepre"><code class="code">let process_fork, process_join =
519
557
  Netmcore_process.def_process process_body
520
558
</code></pre>
521
559
<p>
547
585
as needed. Here is how to do:
548
586
<p>
549
587
 
550
 
<pre><code class="code">let pid = Netmcore_process.start process_fork arg
 
588
<pre class="codepre"><code class="code">let pid = Netmcore_process.start process_fork arg
551
589
</code></pre>
552
590
<p>
553
591
 
573
611
process is terminated. One can get the result value by doing:
574
612
<p>
575
613
 
576
 
<pre><code class="code">let r_opt = Netmcore_process.join process_join pid
 
614
<pre class="codepre"><code class="code">let r_opt = Netmcore_process.join process_join pid
577
615
</code></pre>
578
616
<p>
579
617
 
586
624
If there is no interest in getting results at all, one can also do
587
625
<p>
588
626
 
589
 
<pre><code class="code">Netmcore_process.release_join_point process_join
 
627
<pre class="codepre"><code class="code">Netmcore_process.release_join_point process_join
590
628
</code></pre>
591
629
<p>
592
630
 
601
639
function call like
602
640
<p>
603
641
 
604
 
<pre><code class="code">Netmcore.startup
 
642
<pre class="codepre"><code class="code">Netmcore.startup
605
643
   ~socket_directory:"some_dir" 
606
644
   ~first_process:(fun () -&gt; Netmcore_process.start process_fork arg)
607
645
   ()
619
657
starts process Y. The processes do not much, but let's see:
620
658
<p>
621
659
 
622
 
<pre><code class="code">let c = ref 0
 
660
<pre class="codepre"><code class="code">let c = ref 0
623
661
 
624
662
let body_Y k =
625
663
  k + 1 + !c
669
707
  system.</li>
670
708
</ul>
671
709
 
672
 
<span id="camlboxes"><h2>How to use Camlboxes for passing messages</h2></span>
 
710
<h2 id="camlboxes">How to use Camlboxes for passing messages</h2>
673
711
<p>
674
712
 
675
713
Camlboxes must always be created by the (single) receiver of the
691
729
and Y sends a message to the box of X.
692
730
<p>
693
731
 
694
 
<pre><code class="code">let body_Y box_res =
 
732
<pre class="codepre"><code class="code">let body_Y box_res =
695
733
  let (box_sender : string Netcamlbox.camlbox_sender) = 
696
734
     Netmcore_camlbox.lookup_camlbox_sender box_res in
697
735
  Netcamlbox.camlbox_send box_sender "Hello world"
779
817
very much like marshalling.
780
818
<p>
781
819
 
782
 
<span id="mempools"><h2>How to create and use memory pools</h2></span>
 
820
<h2 id="mempools">How to create and use memory pools</h2>
783
821
<p>
784
822
 
785
823
Now back to the core of Netmulticore. For the remaining data
819
857
Now, the pool is simply created with
820
858
<p>
821
859
 
822
 
<pre><code class="code">let pool = Netmcore_mempool.create_mempool size_in_bytes
 
860
<pre class="codepre"><code class="code">let pool = Netmcore_mempool.create_mempool size_in_bytes
823
861
</code></pre>
824
862
<p>
825
863
 
835
873
explicitly deleted (like files). To do so, just call
836
874
<p>
837
875
 
838
 
<pre><code class="code">Netmcore.release pool
 
876
<pre class="codepre"><code class="code">Netmcore.release pool
839
877
</code></pre>
840
878
<p>
841
879
 
848
886
each started process, e.g.
849
887
<p>
850
888
 
851
 
<pre><code class="code">let pid = 
 
889
<pre class="codepre"><code class="code">let pid = 
852
890
  Netmcore_process.start 
853
891
    ~inherit_resources:`All
854
892
    process_fork arg
867
905
looking for ways how to get nicer reactions.)
868
906
<p>
869
907
 
870
 
<span id="sref"><h2>Shared <code class="code">ref</code>-type variables</h2></span>
 
908
<h2 id="sref">Shared <code class="code">ref</code>-type variables</h2>
871
909
<p>
872
910
 
873
911
Let's now look at a data structure that lives in a shared heap.
887
925
The reference is created by something like
888
926
<p>
889
927
 
890
 
<pre><code class="code">let s = Netmcore_ref.sref pool initial_value
 
928
<pre class="codepre"><code class="code">let s = Netmcore_ref.sref pool initial_value
891
929
</code></pre>
892
930
<p>
893
931
 
896
934
This is comparable to
897
935
<p>
898
936
 
899
 
<pre><code class="code">let r = ref initial_value
 
937
<pre class="codepre"><code class="code">let r = ref initial_value
900
938
</code></pre>
901
939
<p>
902
940
 
920
958
It is possible to assign a new value to <code class="code">s</code>:
921
959
<p>
922
960
 
923
 
<pre><code class="code">Netmcore_ref.assign s new_value
 
961
<pre class="codepre"><code class="code">Netmcore_ref.assign s new_value
924
962
</code></pre>
925
963
<p>
926
964
 
947
985
the value pointed to by a reference:
948
986
<p>
949
987
 
950
 
<pre><code class="code">let v1 = Netmcore_ref.deref_ro s
 
988
<pre class="codepre"><code class="code">let v1 = Netmcore_ref.deref_ro s
951
989
 
952
990
let v2 = Netmcore_ref.deref_c s
953
991
 
999
1037
some inner part of the value is mutable, e.g.
1000
1038
<p>
1001
1039
 
1002
 
<pre><code class="code">type t = { mutable data : string }
 
1040
<pre class="codepre"><code class="code">type t = { mutable data : string }
1003
1041
 
1004
1042
let s = Netmcore_ref.sref pool { data = "initial string" }
1005
1043
</code></pre>
1009
1047
component, as in
1010
1048
<p>
1011
1049
 
1012
 
<pre><code class="code">(Netmcore_ref.deref_ro s).data &lt;- "new string"   (* WARNING - PROBLEMATIC CODE *)
 
1050
<pre class="codepre"><code class="code">(Netmcore_ref.deref_ro s).data &lt;- "new string"   (* WARNING - PROBLEMATIC CODE *)
1013
1051
</code></pre>
1014
1052
<p>
1015
1053
 
1029
1067
Finally, here is a complete example using shared references:
1030
1068
<p>
1031
1069
 
1032
 
<pre><code class="code">let body_Y (pool, c_descr, k) =
 
1070
<pre class="codepre"><code class="code">let body_Y (pool, c_descr, k) =
1033
1071
  let c = Netmcore_sref.sref_of_descr pool c_descr in
1034
1072
  let c_value = Netmcore_sref.deref_ro c in
1035
1073
  k + 1 + c_value
1078
1116
heap in the called function.
1079
1117
<p>
1080
1118
 
1081
 
<span id="descriptors"><h2>Descriptors</h2></span>
 
1119
<h2 id="descriptors">Descriptors</h2>
1082
1120
<p>
1083
1121
 
1084
1122
Shared heaps are very special objects - in particular, the heaps
1123
1161
example, shared references define this as (in <a href="Netmcore_ref.html"><code class="code">Netmcore_ref</code></a>):
1124
1162
<p>
1125
1163
 
1126
 
<pre><code class="code">type 't sref_descr
 
1164
<pre class="codepre"><code class="code">type 't sref_descr
1127
1165
 
1128
1166
val descr_of_sref : 't sref -&gt; 't sref_descr
1129
1167
val sref_of_descr : Netmcore.res_id -&gt; 't sref_descr -&gt; 't sref
1140
1178
supporting descriptors.
1141
1179
<p>
1142
1180
 
1143
 
<span id="mutation"><h2>How to mutate shared values</h2></span>
 
1181
<h2 id="mutation">How to mutate shared values</h2>
1144
1182
<p>
1145
1183
 
1146
1184
Remember this code?
1147
1185
<p>
1148
1186
 
1149
 
<pre><code class="code">(Netmcore_ref.deref_ro s).data &lt;- "new string"   (* WARNING - PROBLEMATIC CODE *)
 
1187
<pre class="codepre"><code class="code">(Netmcore_ref.deref_ro s).data &lt;- "new string"   (* WARNING - PROBLEMATIC CODE *)
1150
1188
</code></pre>
1151
1189
<p>
1152
1190
 
1158
1196
The correct way to do it is this:
1159
1197
<p>
1160
1198
 
1161
 
<pre><code class="code">Netmcore_heap.modify
 
1199
<pre class="codepre"><code class="code">Netmcore_heap.modify
1162
1200
  (Netmcore_ref.heap s)
1163
1201
  (fun mut -&gt;
1164
1202
    (Netmcore_ref.deref_ro s).data &lt;- Netmcore_heap.add mut "new string"
1195
1233
Let's look at this example:
1196
1234
<p>
1197
1235
 
1198
 
<pre><code class="code">type u = { mutable data1 : string;
 
1236
<pre class="codepre"><code class="code">type u = { mutable data1 : string;
1199
1237
           mutable data2 : string;
1200
1238
         }
1201
1239
 
1209
1247
The solution is of course:
1210
1248
<p>
1211
1249
 
1212
 
<pre><code class="code">Netmcore_heap.modify
 
1250
<pre class="codepre"><code class="code">Netmcore_heap.modify
1213
1251
  (Netmcore_ref.heap s)
1214
1252
  (fun mut -&gt;
1215
1253
    let u = Netmcore_ref.deref_ro s in
1230
1268
A little variation of this let us run into a possible problem, though:
1231
1269
<p>
1232
1270
 
1233
 
<pre><code class="code">Netmcore_heap.modify
 
1271
<pre class="codepre"><code class="code">Netmcore_heap.modify
1234
1272
  (Netmcore_ref.heap s)
1235
1273
  (fun mut -&gt;
1236
1274
    let u = Netmcore_ref.deref_ro s in
1262
1300
so that they cannot be collected by the GC:
1263
1301
<p>
1264
1302
 
1265
 
<pre><code class="code">Netmcore_heap.modify
 
1303
<pre class="codepre"><code class="code">Netmcore_heap.modify
1266
1304
  (Netmcore_ref.heap s)
1267
1305
  (fun mut -&gt;
1268
1306
    let u = Netmcore_ref.deref_ro s in
1279
1317
the end of the <code class="code">modify</code> function.
1280
1318
<p>
1281
1319
 
1282
 
<span id="sdata"><h2>Shared data structures</h2></span>
 
1320
<h2 id="sdata">Shared data structures</h2>
1283
1321
<p>
1284
1322
 
1285
1323
Besides references, there are a number of further shared data structures:
1319
1357
The signature is:
1320
1358
<p>
1321
1359
 
1322
 
<pre><code class="code">type ('e,'h) sarray
 
1360
<pre class="codepre"><code class="code">type ('e,'h) sarray
1323
1361
type ('e,'h) sarray_descr
1324
1362
val create : Netmcore.res_id -&gt; 'e array -&gt; 'h -&gt; ('e,'h) sarray
1325
1363
val make : Netmcore.res_id -&gt; int -&gt; 'e -&gt; 'h -&gt; ('e,'h) sarray
1386
1424
allow it to manage descriptors.
1387
1425
<p>
1388
1426
 
1389
 
<span id="sync"><h2>Synchronization</h2></span>
 
1427
<h2 id="sync">Synchronization</h2>
1390
1428
<p>
1391
1429
 
1392
1430
There are three kinds of synchronization devices:
1415
1453
to protect concurrent accesses to <code class="code">x</code>:
1416
1454
<p>
1417
1455
 
1418
 
<pre><code class="code">type t =
 
1456
<pre class="codepre"><code class="code">type t =
1419
1457
  { mutable x : some_type;
1420
1458
    mutable m : Netmcore_mutex.mutex
1421
1459
  }
1425
1463
This record is put into a shared reference:
1426
1464
<p>
1427
1465
 
1428
 
<pre><code class="code">let s = Netmcore_ref.sref { x = ...; m = ... }
 
1466
<pre class="codepre"><code class="code">let s = Netmcore_ref.sref { x = ...; m = ... }
1429
1467
</code></pre>
1430
1468
<p>
1431
1469
 
1439
1477
dummy value one can use during initialization:
1440
1478
<p>
1441
1479
 
1442
 
<pre><code class="code">let s = Netmcore_ref.sref { x = ...; m = Netmcore_mutex.dummy() }
 
1480
<pre class="codepre"><code class="code">let s = Netmcore_ref.sref { x = ...; m = Netmcore_mutex.dummy() }
1443
1481
</code></pre>
1444
1482
<p>
1445
1483
 
1447
1485
mutex is already copied to the shared heap. This is done by:
1448
1486
<p>
1449
1487
 
1450
 
<pre><code class="code">Netmcore_heap.modify
 
1488
<pre class="codepre"><code class="code">Netmcore_heap.modify
1451
1489
  (Netmcore_ref.heap s)
1452
1490
  (fun mut -&gt;
1453
1491
     let r = Netmcore_ref.deref_ro mut in
1463
1501
The mutex can now be used in statements like
1464
1502
<p>
1465
1503
 
1466
 
<pre><code class="code">Netmcore_ref.deref_p (fun r -&gt; Netmcore_mutex.lock r)
 
1504
<pre class="codepre"><code class="code">Netmcore_ref.deref_p (fun r -&gt; Netmcore_mutex.lock r)
1467
1505
</code></pre>
1468
1506
<p>
1469
1507
 
1489
1527
of <code class="code">wait_entry</code> values. Let's look at an example:
1490
1528
<p>
1491
1529
 
1492
 
<pre><code class="code">type t =
 
1530
<pre class="codepre"><code class="code">type t =
1493
1531
  { mutable x : some_type;
1494
1532
    mutable m : Netmcore_mutex.mutex;
1495
1533
    mutable c : Netmcore_condition.condition;
1524
1562
using <code class="code">s</code>. Get it with:
1525
1563
<p>
1526
1564
 
1527
 
<pre><code class="code">let we =
 
1565
<pre class="codepre"><code class="code">let we =
1528
1566
  Netmcore_heap.modify
1529
1567
    (Netmcore_ref.heap s)
1530
1568
    (fun mut -&gt; 
1541
1579
A <code class="code">wait</code> call looks then like:
1542
1580
<p>
1543
1581
 
1544
 
<pre><code class="code">Netmcore_ref.deref_p (fun r -&gt; Netmcore_condition.wait we r.c r.m)
 
1582
<pre class="codepre"><code class="code">Netmcore_ref.deref_p (fun r -&gt; Netmcore_condition.wait we r.c r.m)
1545
1583
</code></pre>
1546
1584
<p>
1547
1585
 
1550
1588
process - we need to create <code class="code">we</code> once for each process.
1551
1589
<p>
1552
1590
 
1553
 
<span id="examples"><h2>Where to find examples</h2></span>
 
1591
<h2 id="examples">Where to find examples</h2>
1554
1592
<p>
1555
1593
 
1556
1594
It is very much recommended to study complete examples before trying
1564
1602
<li><a href="https://godirepo.camlcity.org/svn/lib-ocamlnet2/trunk/code/examples/multicore/"> examples/multicore</a></li>
1565
1603
</ul>
1566
1604
 
1567
 
<span id="impl"><h2>Remarks on the implementation</h2></span>
 
1605
<h2 id="impl">Remarks on the implementation</h2>
1568
1606
<p>
1569
1607
 
1570
1608
The current implementation of shared heaps only uses a single lock for
1591
1629
given back to the memory pool.
1592
1630
<p>
1593
1631
 
1594
 
<span id="diffs"><h2>Some points where Netmulticore is different from multi-threading</h2></span>
 
1632
<h2 id="diffs">Some points where Netmulticore is different from multi-threading</h2>
1595
1633
<p>
1596
1634
 
1597
1635
When porting multi-threaded programs to Netmulticore, you may wonder
1635
1673
cores.
1636
1674
<p>
1637
1675
 
1638
 
<span id="os"><h2>Operating system issues</h2></span>
 
1676
<h2 id="os">Operating system issues</h2>
1639
1677
<p>
1640
1678
 
1641
 
<span id="3_AdministeringPOSIXsharedmemory"><h3>Administering POSIX shared memory</h3></span>
 
1679
<h3 id="3_AdministeringPOSIXsharedmemory">Administering POSIX shared memory</h3>
1642
1680
<p>
1643
1681
 
1644
1682
Many of the data structures described here are actually backed by
1658
1696
<p>
1659
1697
 
1660
1698
The nice aspect of the POSIX API is that shared memory looks very much
1661
 
like files, and in deed, in all implementations I've seen the blocks
 
1699
like files, and in deed, in many implementations I've seen the blocks
1662
1700
appear somewhere in the file system. Typical locations for these files
1663
1701
are <code class="code">/dev/shm</code> and <code class="code">/tmp</code>. The files have names like
1664
1702
<code class="code">mempool_f7e8bdaa</code>, or generally <code class="code">&lt;prefix&gt;_&lt;8hexdigits&gt;</code>. The prefix
1667
1705
are removed.
1668
1706
<p>
1669
1707
 
 
1708
Since Ocamlnet-3.6, one can also delete shared memory administratively
 
1709
with the <code class="code">netplex-admin</code> utility. See <a href="Netplex_admin.html#unlink"><i>Deleting persistent kernel objects</i></a> for
 
1710
details. This method works for all OS. Also, an unlink of old memory
 
1711
is automatically done when the program is restarted.
 
1712
<p>
 
1713
 
1670
1714
Another issue is that OS typically define an upper limit for the
1671
1715
amount of shared memory. This is e.g. 50% of the system RAM for
1672
1716
Linux. There are usually ways to configure this limit.