@@ -59,7 +59,7 @@ def test_atomic_cursor_local_mode_basic():
5959 # Consume with atomic cursor
6060 consumed = []
6161 for _ in range (10 ):
62- data , size = q .read (cursor )
62+ data , size , _ = q .read (cursor )
6363 if data is not None :
6464 value = struct .unpack ("<I" , data [:4 ])[0 ]
6565 consumed .append (value )
@@ -68,7 +68,7 @@ def test_atomic_cursor_local_mode_basic():
6868 assert consumed == list (range (10 )), f"Expected { list (range (10 ))} , got { consumed } "
6969
7070 # Verify no more data
71- data , size = q .read (cursor )
71+ data , size , _ = q .read (cursor )
7272 assert data is None , "Expected no more data"
7373
7474 q .close ()
@@ -104,7 +104,7 @@ def consumer_worker(worker_id, results):
104104 max_consecutive_none = 20 # Give more chances
105105 time .sleep (random .uniform (0.03 , 0.05 ))
106106 while len (consumed ) < num_items and consecutive_none < max_consecutive_none :
107- data , _ = q .read (cursor )
107+ data , size , data_index = q .read (cursor )
108108 if data is None :
109109 consecutive_none += 1
110110 else :
@@ -173,15 +173,15 @@ def consumer_worker(worker_id, results):
173173 consumed = []
174174 no_data_count = 0
175175 while len (consumed ) < num_items // num_threads + 50 : # Over-subscribe
176- data , size = q .read (cursor )
176+ data , size , _ = q .read (cursor )
177177 if data is not None :
178178 no_data_count = 0
179179 value = struct .unpack ("<I" , data [:4 ])[0 ]
180180 consumed .append (value )
181181 time .sleep (random .uniform (0.0003 , 0.0005 ))
182182 else :
183183 no_data_count += 1
184- if no_data_count > 1000 :
184+ if no_data_count > 10000 :
185185 break
186186 time .sleep (0.00001 ) # Wait for producer
187187 results [worker_id ] = consumed
@@ -234,19 +234,21 @@ def consumer_process_worker(queue_name, cursor_name, worker_id, num_items, resul
234234 cursor = AtomicCursor (cursor_shm .buf , 0 )
235235
236236 consumed = []
237- num_no_data = 0
238237
239- with open ('ready' , 'a' ):
240- # Keep consuming until we've collectively consumed all items
241- while cursor .load () < num_items :
242- data , size = q .read (cursor )
243- if data is not None :
244- num_no_data = 0
245- value = struct .unpack ("<I" , data [:4 ])[0 ]
246- consumed .append (value )
247- time .sleep (random .uniform (0.003 , 0.005 ))
248- else :
249- time .sleep (0.000001 )
238+ # Signal that consumer is ready (create/touch the file, then close it immediately)
239+ with open ('ready' , 'a' ) as f :
240+ pass # Just create/touch the file
241+
242+ # Keep consuming until we've collectively consumed all items
243+ while cursor .load () < num_items :
244+ data , size , data_index = q .read (cursor )
245+ if data is not None :
246+ value = struct .unpack ("<I" , data [:4 ])[0 ]
247+ print (f"Process { worker_id } consumed an item { value } @ index { data_index } " )
248+ consumed .append (value )
249+ time .sleep (random .uniform (0.0003 , 0.0005 ))
250+ else :
251+ time .sleep (0.000001 )
250252 results .put ((worker_id , consumed ))
251253
252254 cursor_shm .close ()
@@ -267,6 +269,7 @@ def producer_worker(num_items: int, q: SlickQueue):
267269 data = struct .pack ("<I" , i )
268270 q [idx ][:len (data )] = data
269271 q .publish (idx )
272+ print (f"Produced item { idx } { i } " )
270273 time .sleep (random .uniform (0.001 , 0.003 )) # Slow producer
271274
272275def test_atomic_cursor_shared_memory_mode ():
@@ -394,7 +397,7 @@ def test_atomic_cursor_compare_with_int_cursor():
394397
395398 consumed_atomic = []
396399 for _ in range (num_items ):
397- data , size = q2 .read (cursor )
400+ data , size , _ = q2 .read (cursor )
398401 if data is not None :
399402 value = struct .unpack ("<I" , data [:4 ])[0 ]
400403 consumed_atomic .append (value )
@@ -436,7 +439,7 @@ def test_atomic_cursor_wraparound():
436439 q .publish (idx , sz )
437440
438441 # Consume immediately
439- data , size = q .read (cursor )
442+ data , size , _ = q .read (cursor )
440443 if data is not None :
441444 offset = 0
442445 while size > 0 :
@@ -538,93 +541,6 @@ def test_atomic_cursor_python_cpp_work_stealing_cursor_created_by_py():
538541 print (f"[PASS] C++ work-stealing consumer cursor created by Python test passed: { num_items } items consumed" )
539542
540543
541- def test_atomic_cursor_python_cpp_work_stealing_cursor_created_by_py ():
542- """Test AtomicCursor with a C++ work-stealing consumer, cursor created by Python."""
543- print ("\n === Test: AtomicCursor with C++ Work-Stealing Consumer, cursor created by Python ===" )
544-
545- queue_name = 'test_atomic_cursor_cpp_queue'
546- cursor_name = 'test_cur_cpp_py_created'
547- num_items = 100
548-
549- try :
550- os .remove ('ready' )
551- except Exception :
552- pass
553-
554- # Create shared queue and cursor
555- q = SlickQueue (name = queue_name , size = 128 , element_size = 32 )
556- cursor_shm = SharedMemory (name = cursor_name , create = True , size = 8 )
557- cursor = AtomicCursor (cursor_shm .buf , 0 )
558- cursor .store (0 )
559-
560- actual_name = q .get_shm_name ()
561- actual_cursor_name = cursor_shm ._name
562-
563- # Start C++ consumer process
564- cpp_consumer = find_cpp_executable ("cpp_work_stealing_consumer" )
565- output_file = Path (__file__ ).parent / "cpp_work_stealing_consumer_output.txt"
566- cpp_consumer_proc = subprocess .Popen ([
567- cpp_consumer ,
568- actual_name ,
569- str (num_items ),
570- str (32 ), # element size
571- actual_cursor_name ,
572- str (output_file )
573- ], stdout = subprocess .PIPE , stderr = subprocess .PIPE )
574-
575- # Start consumer processes
576- results = MPQueue ()
577- py_consumer_proc = Process (
578- target = consumer_process_worker ,
579- args = (queue_name , cursor_name , 0 , num_items , results )
580- )
581- py_consumer_proc .start ()
582-
583- # Start producer
584- producer = Thread (target = producer_worker , args = (num_items , q ))
585- producer .start ()
586-
587- producer .join ()
588- py_consumer_proc .join ()
589-
590- stdout , stderr = cpp_consumer_proc .communicate ()
591-
592- print (stdout .decode ())
593- print (stderr .decode ())
594- if cpp_consumer_proc .returncode != 0 :
595- print (stderr , file = sys .stderr )
596- raise RuntimeError (f"C++ consumer failed with code { cpp_consumer_proc .returncode } " )
597-
598- # Verify consumed data
599- consumed = []
600- with open (output_file , 'r' ) as f :
601- for line in f :
602- item , _ = map (int , line .strip ().split ())
603- consumed .append (item )
604-
605- py_result = results .get (timeout = 5 )
606- py_consumed = py_result [1 ]
607- print ("Python consumer consumed:" , len (py_consumed ))
608- consumed .extend (item for item in py_consumed )
609-
610- # Check all items consumed
611- assert len (consumed ) == num_items , f"Expected { num_items } items, got { len (consumed )} "
612-
613- # Check data integrity
614- expected = set (range (num_items ))
615- actual = set (consumed )
616- assert expected == actual , f"Data mismatch between produced and consumed"
617-
618- # Cleanup
619- cursor_shm .close ()
620- cursor_shm .unlink ()
621- q .close ()
622- q .unlink ()
623- if output_file .exists ():
624- output_file .unlink ()
625-
626- print (f"[PASS] C++ work-stealing consumer cursor created by Python test passed: { num_items } items consumed" )
627-
628544def test_atomic_cursor_python_cpp_work_stealing_cursor_created_by_cpp ():
629545 """Test AtomicCursor with a C++ work-stealing consumer, cursor created by C++."""
630546 print ("\n === Test: AtomicCursor with C++ Work-Stealing Consumer, cursor created by C++ ===" )
@@ -641,15 +557,20 @@ def test_atomic_cursor_python_cpp_work_stealing_cursor_created_by_cpp():
641557 # Create shared queue and cursor
642558 q = SlickQueue (name = queue_name , size = 128 , element_size = 32 )
643559
560+ actual_queue_name = q .get_shm_name ()
561+
562+ from slick_queue_py .atomic_ops import validate_shm_name
563+ actual_cursor_name = validate_shm_name (cursor_name ) # Created by C++ process
564+
644565 # Start C++ consumer process
645566 cpp_consumer = find_cpp_executable ("cpp_work_stealing_consumer" )
646567 output_file = Path (__file__ ).parent / "cpp_work_stealing_consumer_output.txt"
647568 cpp_consumer_proc = subprocess .Popen ([
648569 cpp_consumer ,
649- queue_name ,
570+ actual_queue_name ,
650571 str (num_items ),
651572 str (32 ), # element size
652- cursor_name ,
573+ actual_cursor_name ,
653574 str (output_file )
654575 ], stdout = subprocess .PIPE , stderr = subprocess .PIPE )
655576
0 commit comments