141 lines
4.0 KiB
C
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);
|
|
}
|