Files
my_device_handler/my_device_handler.c
2026-03-13 16:38:39 +01:00

141 lines
4.0 KiB
C

#include "registries_items.h"
#include <stdio.h>
#include <stdlib.h>
#include "registries.h"
#include "my_device_handler.h"
void reinitialize_all_devices_wrote_barrier( int childCount){
int anyerror = pthread_barrier_init( &all_devices_wrote_barrier, NULL, 1 + childCount);
if(anyerror){
fprintf( stderr, "all_devices_wrote_barrier reinitialization error\n");
exit(1);
}
}
void reinitialize_devices_write_new_round_barrier( int childCount){
int anyerror = pthread_barrier_init( &devices_write_new_round_barrier, NULL, 1 + childCount);
if(anyerror){
fprintf( stderr, "devices_write_new_round_barrier reinitialization error\n");
exit(1);
}
}
int device_handler_init(){
global_queue_init();
reinitialize_all_devices_wrote_barrier(0);
reinitialize_devices_write_new_round_barrier(0);
initialize_device_added_flag_barrier();
return 0;
}
int device_handler_add( const char *path){
if( is_listed_as_active( path)){ /* already enlisted */
return 0;
}
if( is_listed_for_insertion( path)){ /* already requested the insertion */
return 0;
}
if( is_listed_for_removal( path)){ /* undo the removal request */
remove_from_update_list( path);
return 0;
}
add_to_update_list( path, INSERT); /* request insertion */
return 0;
}
int device_handler_remove( const char *path){
printf("go with remove device\n");
if( is_listed_for_removal( path)){ /* already requested the removal */
printf("-> was alredy listed for removal\n");
return 0;
}
if( is_listed_for_insertion( path)){ /* undo the insertion request */
printf("-> was listed for insertion, remove request\n");
remove_from_update_list( path);
return 0;
}
if( ! is_listed_as_active( path)){ /* is not enlisted anywhere */
printf("-> is not listed as active\n");
return 0;
}
printf("-> have to enlist for removal\n");
add_to_update_list( path, REMOVE); /* request removal */
return 0;
}
/* each device thread
takes the mutex, writes its events, releases
then reaches the all_wrote barrier
then reaches the new_round barrier
the main thread instead
reaches the all_wrote barrier, releasing it
reads all the events (dispatching them in some way or another)
gets the count of devices waiting to be added and the count of those waiting to be removed
if there are pending additions and/or removals
calculate newChildCount
if newChildCount != current
recreates the all_wrote barrier with a count of (1 [itself] + newChildCount )
adds all the devices waiting to be added, same for removals
( placed here for preventing actions from the device threads listed for removal )
reaches the new_round barrier, releasing it
if newChildCount != current
recreates the new_round barrier with a count of (1 [itself] + newChildCount )
( the device list update was here, but this could have caused the lock on the first barrier of some of the device theads listed for removal,
it is unspecified how the barrier behaves upon the destruction of a waiting thread
they could have also stored some new event, causing minor inconsistencies
)
*/
int device_handler_poll_events( device_event** events){
int currentChildCount;
int update_delta;
int newChildCount;
int events_count;
currentChildCount = active_list_count();
pthread_barrier_wait( &all_devices_wrote_barrier);
/* remove events from queue */
events_count = drain_events_into( events);
update_delta = update_list_get_delta();
newChildCount = currentChildCount + update_delta;
if( newChildCount != currentChildCount){
reinitialize_all_devices_wrote_barrier( newChildCount);
}
/* here update the devices list */
update_list_drain_into_active();
pthread_barrier_wait( &devices_write_new_round_barrier);
if( newChildCount != currentChildCount){
reinitialize_devices_write_new_round_barrier( newChildCount);
currentChildCount = newChildCount;
}
/* return the number of events*/
return events_count;
}
void device_handler_destroy_events( device_event *events){
/* no need for items destruction (they are static objects) */
free( events);
}