@@ -252,58 +252,90 @@ static void ets_delete_all_tables(struct Ets *ets, GlobalContext *global)
252
252
ets_delete_tables_internal (ets , true_pred , NULL , global );
253
253
}
254
254
255
- EtsErrorCode ets_insert ( term ref , term entry , Context * ctx )
255
+ static EtsErrorCode ets_table_insert ( struct EtsTable * ets_table , term entry , Context * ctx )
256
256
{
257
- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessWrite ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessWrite );
258
- if (ets_table == NULL ) {
259
- return EtsTableNotFound ;
260
- }
261
-
262
257
if (ets_table -> access_type != EtsAccessPublic && ets_table -> owner_process_id != ctx -> process_id ) {
263
- SMP_UNLOCK (ets_table );
264
258
return EtsPermissionDenied ;
265
259
}
266
260
267
261
if ((size_t ) term_get_tuple_arity (entry ) < (ets_table -> keypos + 1 )) {
268
- SMP_UNLOCK (ets_table );
269
262
return EtsBadEntry ;
270
263
}
271
264
272
265
Heap * heap = malloc (sizeof (Heap ));
273
266
if (IS_NULL_PTR (heap )) {
274
- SMP_UNLOCK (ets_table );
275
267
return EtsAllocationFailure ;
276
268
}
277
269
size_t size = (size_t ) memory_estimate_usage (entry );
278
270
if (memory_init_heap (heap , size ) != MEMORY_GC_OK ) {
279
271
free (heap );
280
- SMP_UNLOCK (ets_table );
281
272
return EtsAllocationFailure ;
282
273
}
283
274
284
275
term new_entry = memory_copy_term_tree (heap , entry );
285
276
term key = term_get_tuple_element (new_entry , (int ) ets_table -> keypos );
286
277
287
- EtsErrorCode ret = EtsOk ;
278
+ EtsErrorCode result = EtsOk ;
288
279
EtsHashtableErrorCode res = ets_hashtable_insert (ets_table -> hashtable , key , new_entry , EtsHashtableAllowOverwrite , heap , ctx -> global );
289
280
if (UNLIKELY (res != EtsHashtableOk )) {
290
- ret = EtsAllocationFailure ;
281
+ result = EtsAllocationFailure ;
291
282
}
292
283
293
- SMP_UNLOCK (ets_table );
284
+ return result ;
285
+ }
294
286
295
- return ret ;
287
+ static EtsErrorCode ets_table_insert_list (struct EtsTable * ets_table , term list , Context * ctx )
288
+ {
289
+ term iter = list ;
290
+
291
+ while (term_is_nonempty_list (iter )) {
292
+ term tuple = term_get_list_head (iter );
293
+ iter = term_get_list_tail (iter );
294
+ if (!term_is_tuple (tuple ) || (size_t ) term_get_tuple_arity (tuple ) < (ets_table -> keypos + 1 )) {
295
+ return EtsBadEntry ;
296
+ }
297
+ }
298
+ if (!term_is_nil (iter )) {
299
+ return EtsBadEntry ;
300
+ }
301
+
302
+ while (term_is_nonempty_list (list )) {
303
+ term tuple = term_get_list_head (list );
304
+ EtsErrorCode result = ets_table_insert (ets_table , tuple , ctx );
305
+ if (UNLIKELY (result != EtsOk )) {
306
+ AVM_ABORT (); // Abort because operation might not be atomic.
307
+ }
308
+
309
+ list = term_get_list_tail (list );
310
+ }
311
+
312
+ return EtsOk ;
296
313
}
297
314
298
- EtsErrorCode ets_lookup (term ref , term key , term * ret , Context * ctx )
315
+ EtsErrorCode ets_insert (term name_or_ref , term entry , Context * ctx )
299
316
{
300
- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
317
+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessWrite ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessWrite );
301
318
if (ets_table == NULL ) {
302
319
return EtsTableNotFound ;
303
320
}
304
321
322
+ EtsErrorCode result ;
323
+ if (term_is_tuple (entry )) {
324
+ result = ets_table_insert (ets_table , entry , ctx );
325
+ } else if (term_is_list (entry )) {
326
+ result = ets_table_insert_list (ets_table , entry , ctx );
327
+ } else {
328
+ result = EtsBadEntry ;
329
+ }
330
+
331
+ SMP_UNLOCK (ets_table );
332
+
333
+ return result ;
334
+ }
335
+
336
+ static EtsErrorCode ets_table_lookup (struct EtsTable * ets_table , term key , term * ret , Context * ctx )
337
+ {
305
338
if (ets_table -> access_type == EtsAccessPrivate && ets_table -> owner_process_id != ctx -> process_id ) {
306
- SMP_UNLOCK (ets_table );
307
339
return EtsPermissionDenied ;
308
340
}
309
341
@@ -316,24 +348,35 @@ EtsErrorCode ets_lookup(term ref, term key, term *ret, Context *ctx)
316
348
size_t size = (size_t ) memory_estimate_usage (res );
317
349
// allocate [object]
318
350
if (UNLIKELY (memory_ensure_free_opt (ctx , size + CONS_SIZE , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
319
- SMP_UNLOCK (ets_table );
320
351
return EtsAllocationFailure ;
321
352
}
322
353
term new_res = memory_copy_term_tree (& ctx -> heap , res );
323
354
* ret = term_list_prepend (new_res , term_nil (), & ctx -> heap );
324
355
}
325
- SMP_UNLOCK (ets_table );
326
356
327
357
return EtsOk ;
328
358
}
329
359
330
- EtsErrorCode ets_lookup_element (term ref , term key , size_t pos , term * ret , Context * ctx )
360
+ EtsErrorCode ets_lookup (term name_or_ref , term key , term * ret , Context * ctx )
361
+ {
362
+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
363
+ if (ets_table == NULL ) {
364
+ return EtsTableNotFound ;
365
+ }
366
+
367
+ EtsErrorCode result = ets_table_lookup (ets_table , key , ret , ctx );
368
+ SMP_UNLOCK (ets_table );
369
+
370
+ return result ;
371
+ }
372
+
373
+ EtsErrorCode ets_lookup_element (term name_or_ref , term key , size_t pos , term * ret , Context * ctx )
331
374
{
332
375
if (UNLIKELY (pos == 0 )) {
333
376
return EtsBadPosition ;
334
377
}
335
378
336
- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
379
+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
337
380
if (ets_table == NULL ) {
338
381
return EtsTableNotFound ;
339
382
}
@@ -368,9 +411,9 @@ EtsErrorCode ets_lookup_element(term ref, term key, size_t pos, term *ret, Conte
368
411
return EtsOk ;
369
412
}
370
413
371
- EtsErrorCode ets_delete (term ref , term key , term * ret , Context * ctx )
414
+ EtsErrorCode ets_delete (term name_or_ref , term key , term * ret , Context * ctx )
372
415
{
373
- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
416
+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
374
417
if (ets_table == NULL ) {
375
418
return EtsTableNotFound ;
376
419
}
0 commit comments