Es la mesa en la que se van a sentar los coders a programar. Cada mesa tiene unas “condiciones de trabajo”, esas condiciones son los atributos.

typedef struct s_desk t_desk;
struct s_desk
{
long number_of_coders; // cantidad de coders (entra por parametro)
long long time_to_burnout; // (entra por parametros)
long long time_to_compile; // (entra por parametros)
long long time_to_debug; // (entra por parametros)
long long time_to_refactor; // (entra por parametros)
long number_of_compiles_required; // (entra por parametros)
long long dongle_cooldown; // (entra por parametros)
char *scheduler; // fifo o edf (entra por parametros)
unsigned long start_simulation; // aquí se guardará el id del hilo monitor
bool end_simulation; // debe cambiar a true cuando los coders se agotan o terminamos las compilaciones
long start_time; // momento de inicio de la simulación
pthread_mutex_t log_mutex; // mutex para escribir en la terminal
pthread_mutex_t sim_mutex; // mutex para revisar si la simulación ha terminado o debe terminar
pthread_mutex_t dongles_mutex; // mutex para acceder al array de dongles
pthread_cond_t dongles_cond; // cond para esperar condiciones en el mutex de dongle
t_dongle *dongles; // un array de todos los dongles (usb) que tiene la mesa de coworking
t_coder *coders; // un array de todos los coders que se van a sentar en la mesa a trabajar
};
Cada coder que se va a sentar a la mesa a trabajar. Elles también tienen unas condiciones laborales, entre esas, solo puede usar los dongles (usb) de su izquierda y de su derecha:

typedef struct s_coder t_coder;
struct s_coder
{
int id; // id de trabajador
long compiler_counter; // las compilaciones que ha hecho
bool comp_done; // True cuando termine las compilaciones requeridas
long last_comp_time; // Última vez que empezó a compilar
t_dongle *left_dongle; // un puntero al dongle de su izquierda -> señalará al array de dongles en el desk
t_dongle *right_dongle; // un puntero al dongle de su derecha -> señalará al array de dongles en el desk
pthread_t thread_id; // aqui se guardará el id del hilo de cada coder
t_desk *desk; // un puntero a la mesa en la que se sienta (esto ayudará a poder llegar a los atributos de desk desde coder)
};
Son las herramientas de trabajo, un poco precarias:

typedef s_dongle t_dongle;
struct s_dongle
{
int dongle_id; // id del dongle
long free_at; // timestamp en el que termina el cooldown
t_queue dongle_queue; // cola de prioridad fifo o edf (cada dongle tiene su cola de espera)
int holding_coder_id; // quien lo tiene ahora, -1 si está libre
};
Para el uso de cada dongle, el coder debe apuntar su nombre en una lista de espera. Para esta el funcionamiento de esta lista también he usado struct:
Una lista simple
typedef s_queue t_queue;
struct s_queue
{
t_queue_item *array; // array de items (los nombres de los coders que esperan para usar este dongle)
int size; // el tamaño de la lista que hay que ir actualizando cada vez que se añada a alguien.
};
El papelito del turno que tiene cada coder.

typedef s_queue_item t_queue_item;
struct s_queue_item
{
int coder_id; // el id del coder que se apuntó a la lista
long long priority; // si como parametros recibimos fifo, esto será el timestamp del momento en que se apunta. Si recibimos edf será el tiempo que le queda antes de agotarse.
};