natsStatus natsTimer_Create(natsTimer **timer, natsTimerCb timerCb, natsTimerStopCb stopCb, int64_t interval, void* closure) { natsStatus s = NATS_OK; natsTimer *t = (natsTimer*) NATS_CALLOC(1, sizeof(natsTimer)); if (t == NULL) return nats_setDefaultError(NATS_NO_MEMORY); t->refs = 1; t->cb = timerCb; t->stopCb = stopCb; t->closure = closure; s = natsMutex_Create(&(t->mu)); if (s == NATS_OK) { // Doing so, so that nats_resetTimer() does not try to remove the timer // from the list (since it is new it would not be there!). t->stopped = true; nats_resetTimer(t, interval); *timer = t; } else _freeTimer(t); return NATS_UPDATE_ERR_STACK(s); }
natsStatus natsParser_Create(natsParser **newParser) { natsParser *parser = (natsParser *) NATS_CALLOC(1, sizeof(natsParser)); if (parser == NULL) return NATS_NO_MEMORY; *newParser = parser; return NATS_OK; }
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 natsMutex_Create(natsMutex **newMutex) { natsMutex *m = NATS_CALLOC(1, sizeof(natsMutex)); if (m == NULL) return NATS_NO_MEMORY; if (gLockSpinCount > 0) InitializeCriticalSectionAndSpinCount(m, (DWORD) gLockSpinCount); else InitializeCriticalSection(m); *newMutex = m; return NATS_OK; }
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); }