static void _freeSubscription(natsSubscription *sub) { natsMsg *m; if (sub == NULL) return; while ((m = sub->msgList.head) != NULL) { sub->msgList.head = m->next; natsMsg_Destroy(m); } NATS_FREE(sub->subject); NATS_FREE(sub->queue); natsTimer_Destroy(sub->signalTimer); if (sub->deliverMsgsThread != NULL) { natsThread_Detach(sub->deliverMsgsThread); natsThread_Destroy(sub->deliverMsgsThread); } natsCondition_Destroy(sub->cond); natsMutex_Destroy(sub->mu); natsConn_release(sub->conn); NATS_FREE(sub); }
void natsThread_Destroy(natsThread *t) { if (t == NULL) return; NATS_FREE(t); }
void natsMutex_Destroy(natsMutex *m) { if (m == NULL) return; DeleteCriticalSection(m); NATS_FREE(m); }
static void _freeTimer(natsTimer *t) { if (t == NULL) return; natsMutex_Destroy(t->mu); NATS_FREE(t); }
static unsigned __stdcall _threadStart(void* arg) { struct threadCtx *c = (struct threadCtx*) arg; c->entry(c->arg); NATS_FREE(c); return 0; }
void natsThread_Destroy(natsThread *t) { if (t == NULL) return; CloseHandle(t->t); NATS_FREE(t); }
static void* _threadStart(void *arg) { struct threadCtx *c = (struct threadCtx*) arg; c->entry(c->arg); NATS_FREE(c); nats_ReleaseThreadMemory(); return NULL; }
void natsParser_Destroy(natsParser *parser) { if (parser == NULL) return; natsBuf_Cleanup(&(parser->ma.subjectRec)); natsBuf_Cleanup(&(parser->ma.replyRec)); natsBuf_Cleanup(&(parser->argBufRec)); natsBuf_Cleanup(&(parser->msgBufRec)); NATS_FREE(parser); }
natsStatus natsThread_Create(natsThread **thread, natsThreadCb cb, void *arg) { struct threadCtx *ctx = NULL; natsThread *t = NULL; natsStatus s = NATS_OK; int err; ctx = (struct threadCtx*) NATS_CALLOC(1, sizeof(*ctx)); t = (natsThread*) NATS_CALLOC(1, sizeof(natsThread)); if ((ctx == NULL) || (t == NULL)) s = nats_setDefaultError(NATS_NO_MEMORY); if (s == NATS_OK) { ctx->entry = cb; ctx->arg = arg; err = pthread_create(t, NULL, _threadStart, ctx); if (err) s = nats_setError(NATS_SYS_ERROR, "pthread_create error: %d", errno); } if (s == NATS_OK) { *thread = t; } else { NATS_FREE(ctx); NATS_FREE(t); } return s; }
natsStatus natsThread_Create(natsThread **thread, natsThreadCb cb, void *arg) { struct threadCtx *ctx = NULL; natsThread *t = NULL; natsStatus s = NATS_OK; ctx = (struct threadCtx*) NATS_CALLOC(1, sizeof(*ctx)); t = (natsThread*) NATS_CALLOC(1, sizeof(natsThread)); if ((ctx == NULL) || (t == NULL)) s = NATS_NO_MEMORY; if (s == NATS_OK) { ctx->entry = cb; ctx->arg = arg; t->t = (HANDLE) _beginthreadex(NULL, 0, _threadStart, ctx, 0, NULL); if (t->t == NULL) s = NATS_NO_MEMORY; else t->id = GetThreadId(t->t); } if (s == NATS_OK) { *thread = t; } else { NATS_FREE(ctx); NATS_FREE(t); } return s; }
natsStatus natsSub_create(natsSubscription **newSub, natsConnection *nc, const char *subj, const char *queueGroup, natsMsgHandler cb, void *cbClosure, bool noDelay) { natsStatus s = NATS_OK; natsSubscription *sub = NULL; sub = (natsSubscription*) NATS_CALLOC(1, sizeof(natsSubscription)); if (sub == NULL) return nats_setDefaultError(NATS_NO_MEMORY); s = natsMutex_Create(&(sub->mu)); if (s != NATS_OK) { NATS_FREE(sub); return NATS_UPDATE_ERR_STACK(s); } natsConn_retain(nc); sub->refs = 1; sub->conn = nc; sub->msgCb = cb; sub->msgCbClosure = cbClosure; sub->noDelay = noDelay; sub->msgsLimit = nc->opts->maxPendingMsgs; sub->bytesLimit = nc->opts->maxPendingMsgs * 1024; sub->signalLimit = (int)(sub->msgsLimit * 0.75); sub->subject = NATS_STRDUP(subj); if (sub->subject == NULL) s = nats_setDefaultError(NATS_NO_MEMORY); if ((s == NATS_OK) && (queueGroup != NULL) && (strlen(queueGroup) > 0)) { sub->queue = NATS_STRDUP(queueGroup); if (sub->queue == NULL) s = nats_setDefaultError(NATS_NO_MEMORY); } if (s == NATS_OK) s = natsCondition_Create(&(sub->cond)); if ((s == NATS_OK) && !(sub->noDelay)) { // Set the interval to any value, really, it will get reset to // a smaller value when the delivery thread should be signaled. sub->signalTimerInterval = 10000; // Let's not rely on the created timer acquiring the lock that // would make it safe to retain only on success. _retain(sub); s = natsTimer_Create(&(sub->signalTimer), _signalMsgAvailable, _signalTimerStopped, sub->signalTimerInterval, (void*) sub); if (s != NATS_OK) _release(sub); } if ((s == NATS_OK) && (cb != NULL)) { // Let's not rely on the created thread acquiring the lock that // would make it safe to retain only on success. _retain(sub); // If we have an async callback, start up a sub specific // thread to deliver the messages. s = natsThread_Create(&(sub->deliverMsgsThread), natsSub_deliverMsgs, (void*) sub); if (s != NATS_OK) _release(sub); } if (s == NATS_OK) *newSub = sub; else natsSub_release(sub); return NATS_UPDATE_ERR_STACK(s); }