blob: d12872eaf53edde39be9649d6182a96acdecb088 [file] [log] [blame]
#include "vision/PacketNotifier.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
namespace frc971 {
namespace vision {
void PacketNotifier::RegisterSender(){
close(fd[1]);
}
void PacketNotifier::RegisterReciever(){
close(fd[0]);
}
PacketNotifier *PacketNotifier::MMap(size_t data_size){
PacketNotifier *data;
data = (PacketNotifier *)mmap(NULL, ((data_size * 3 + 4095 + sizeof(PacketNotifier)) / 4096) * 4096,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
data->data_size = data_size;
socketpair(PF_LOCAL, SOCK_STREAM, 0, data->fd);
for(int i = 0;i < 3;i++){
data->buffs[i] = (uint8_t *)data + (sizeof(PacketNotifier) + i * data_size);
}
void *place = &(data->mutex);
*((int *)place) = 0; // The Mutex class needs a placement new operator. (you know, keep the masses happy);
data->in_flight = false;
data->to_send = -1;
data->sending = -1;
return data;
}
void *PacketNotifier::GetBuffer(){
mutex.Lock();
for(int i = 0; i < 3 ; i++){ //search for open spot.
if(i != sending && i != to_send){ //open
filling = i;
mutex.Unlock();
//printf("leasing out to fill buff # %d\n",i);
return buffs[i];
}
}
mutex.Unlock();
//printf("Error in the fabric of the universe\n");
exit(-42);
}
void PacketNotifier::Notify(){
mutex.Lock();
to_send = filling;
filling = -1;
mutex.Unlock();
// wall error
if(write(fd[0],"\n",1)) {}
}
void PacketNotifier::DataSent(const void * /*data*/, size_t /*datalen*/){
//printf("packet_sent: %d; fill: %d; to_send: %d \n",sending,filling,to_send);
mutex.Lock();
sending = -1;
mutex.Unlock();
in_flight = false;
}
bool PacketNotifier::GetData(char **place_to_put,size_t *length){
if(in_flight) return false;
mutex.Lock();
*length = data_size;
*place_to_put = (char *)buffs[to_send];
sending = to_send;
to_send = -1;
mutex.Unlock();
in_flight = true;
return true;
}
} // namespace vision
} // namespace frc971