/* * UPIWIN - Micro Pi Windowing Framework Kernel * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *------------------------------------------------------------------------- */ #include #include #include #include "wintype.h" #include "time_func.h" #include "msg_queue.h" PMSG_QUEUE Mq_alloc(UINT32 nentries) { int sz = sizeof(MSG_QUEUE) + (nentries * sizeof(MSG)); PMSG_QUEUE rc; rc = (PMSG_QUEUE)malloc(sz); if (!rc) return NULL; memset(rc, 0, sz); rc->startbound = &(rc->messagestore[0]); rc->endbound = rc->startbound + nentries; rc->head = rc->tail = rc->startbound; rc->nentries = nentries; pthread_mutex_init(&(rc->mutex), NULL); return rc; } void Mq_destroy(PMSG_QUEUE queue) { pthread_mutex_destroy(&(queue->mutex)); free(queue); } static void post_internal(PMSG_QUEUE queue, PMSG msg) { PMSG nexttail; pthread_mutex_lock(&(queue->mutex)); nexttail = queue->tail + 1; if (nexttail == queue->endbound) nexttail = queue->startbound; if (nexttail != queue->head) { memcpy(queue->tail, msg, sizeof(MSG)); queue->tail = nexttail; } /* else drop the message silently */ pthread_mutex_unlock(&(queue->mutex)); } void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs) { MSG tmpmsg; memset(&tmpmsg, 0, sizeof(MSG)); tmpmsg.target = target; tmpmsg.message = message; if (nattrs > MSG_ATTRCOUNT) nattrs = MSG_ATTRCOUNT; if (nattrs > 0) memcpy(&(tmpmsg.attrs), attrs, sizeof(UINT_PTR) * nattrs); tmpmsg.timestamp = Time_since_start(); post_internal(queue, &tmpmsg); } void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2) { MSG tmpmsg; memset(&tmpmsg, 0, sizeof(MSG)); tmpmsg.target = target; tmpmsg.message = message; tmpmsg.attrs[0] = attr1; tmpmsg.attrs[1] = attr2; tmpmsg.timestamp = Time_since_start(); post_internal(queue, &tmpmsg); } BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags) { BOOL rc = FALSE; PMSG nexthead; pthread_mutex_lock(&(queue->mutex)); if (queue->head != queue->tail) { nexthead = queue->head + 1; if (nexthead == queue->endbound) nexthead = queue->startbound; memcpy(msg, queue->head, sizeof(MSG)); if (flags & PEEK_REMOVE) queue->head = nexthead; rc = TRUE; } pthread_mutex_unlock(&(queue->mutex)); return rc; } BOOL Mq_is_empty(PMSG_QUEUE queue) { BOOL rc; pthread_mutex_lock(&(queue->mutex)); rc = (queue->head == queue->tail); pthread_mutex_unlock(&(queue->mutex)); return rc; }