---
source_url: https://www.pubnub.com/docs/sdks/posix-cpp/api-reference/misc
title: Utility Methods API for POSIX C++ SDK
updated_at: 2026-05-25T11:28:49.599Z
sdk_name: PubNub POSIX C++ SDK
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Utility Methods API for POSIX C++ SDK

PubNub POSIX C++ SDK

The methods on this page are utility methods that don't fit into other categories.

## Class pubnub::subloop

### Declaration

`namespace pubnub { class subloop; }`

### Description

A helper class for a subscribe loop. Supports both a `piecemal`, message-by-message, interface and a `callback-like` interface.

## Constructor

### Declaration

`subloop(context &ctx, std::string channel);`

### Description

Creates a subscribe loop, ready to do the looping. We assume that the `@p` `ctx` PubNub context will be valid throughout the lifetime of this object.

### Parameters

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| ctx | pubnub::context | Yes |  | The PubNub context to use for the loop. |
| channel | std::string | Yes |  | The channel(s) to subscribe to in the loop. |

### Sample code

```cpp
pubnub::subloop sublup(ctx, "hello_world");
```

## Enums

### Enum type: pubnub_res

Result codes for Functions and transactions.

### Members

#### PNR_OK

Success. Transaction finished successfully.

#### PNR_ADDR_RESOLUTION_FAILED

Pubnub host name resolution failed. We failed to get an IP address from the PubNub host name (`origin`). Most of the time, this comes down to a DNS error.

#### PNR_CONNECT_FAILED

Connecting to Pubnub server failed. Most often, this means a network outage, but could be many things. If using `SSL/TLS`, it could be some of its errors.

#### PNR_CONNECTION_TIMEOUT

A time-out happened in the network. Mostly, this is because a network outage happened while being connected to the PubNub server, but could be other things.

#### PNR_TIMEOUT

Time-out before the request has completed. This is reported for a time-out detected by PubNub client itself, not some reported by others (that is, the `TCP/IP` stack).

#### PNR_ABORTED

Connection to Pubnub aborted (in most cases, a `TCP` reset was received).

#### PNR_IO_ERROR

Communication error (network or `HTTP` response format).

#### PNR_HTTP_ERROR

`HTTP` error. Call `pubnub_last_http_code()` to get the error code.

#### PNR_FORMAT_ERROR

Unexpected input in received `JSON`.

#### PNR_CANCELLED

Request cancelled by user.

#### PNR_STARTED

Transaction started. Await the outcome.

#### PNR_IN_PROGRESS

Transaction (already) ongoing. Can't start a new transaction while the old one is in progress.

#### PNR_RX_BUFF_NOT_EMPTY

Receive buffer (from previous transaction) not read, new subscription not allowed.

#### PNR_TX_BUFF_TOO_SMALL

The buffer is too small. Increase `#PUBNUB_BUF_MAXLEN`.

#### PNR_INVALID_CHANNEL

Channel specification / name is invalid.

#### PNR_PUBLISH_FAILED

Publish transaction failed - error returned from Pubnub. To see the reason describing the failure, call `pubnub_last_publish_result()`.

#### PNR_CHANNEL_REGISTRY_ERROR

A transaction related to channel registry failed - error returned from Pubnub. To see the reason describing the failure, get the value for key `message` from the response (which is a `JSON` object) and value for key `status` for the numeric code of the error.

#### PNR_REPLY_TOO_BIG

Reply is too big to fit in our reply buffer. This same error is reported if the reply buffer is statically or dynamically allocated.

### Enum type: pubnub_trans

Type of Pubnub operation/transaction.

### Members

#### PBTT_NONE

No transaction at all.

#### PBTT_SUBSCRIBE

Subscribe operation/transaction.

#### PBTT_PUBLISH

Publish operation/transaction.

#### PBTT_LEAVE

Leave channel(s) operation/transaction.

#### PBTT_TIME

Time (get from Pubnub server) operation/transaction.

#### PBTT_HISTORY

History V2 (get message history for the channel from Pubnub server) operation/transaction.

#### PBTT_HERENOW

Here-now (get UUIDs of currently present users in channel(s)) operation/transaction.

#### PBTT_GLOBAL_HERENOW

Here-now (get UUIDs of currently present users in channel(s)) operation/transaction.

#### PBTT_WHERENOW

Where-now (get channels in which an user (identified by UUID) is currently present) operation/transaction.

#### PBTT_SET_STATE

Set state (for a user (identified by UUID) on channel(s)) operation/transaction.

#### PBTT_STATE_GET

Get state (for a user (identified by UUID) on channel(s)) operation/transaction.

#### PBTT_REMOVE_CHANNEL_GROUP

Remove a channel group (from the channel-registry) operation/transaction.

#### PBTT_REMOVE_CHANNEL_FROM_GROUP

Remove a channel from a channel group (in the channel-registry) operation/transaction.

#### PBTT_ADD_CHANNEL_TO_GROUP

Add a channel to a channel group (in the channel-registry) operation/transaction.

#### PBTT_LIST_CHANNEL_GROUP

Get a list of all channels in a channel group (from the channel-registry) operation/transaction.

## Execute the loop

Executes a `full subscribe loop`, calling the `@p` `f` functional object on each message received or on error in retrieving message(s). To stop the loop, return any integer != 0 from `@p` `f`.

### Method(s)

#### Declaration

`void loop(std::function<int(std::string, context&, pubnub_res)> f);`

#### Parameters

| Parameter | Description |
| --- | --- |
| `f` *Type: `std::function<int(std::string, context&, pubnub_res)>` | Functional object to be called. First parameter is the message, second the context used for the loop and the third is the result of the transaction. Functional object should return `0` to continue the loop and anything != 0 to stop the loop. |

### Sample code

```cpp
sublup.loop([](std::string msg, pubnub::context&, pubnub_res res) {
    if (PNR_OK != res) {
        std::cout << "Getting message failed with code: " << res;
        return -1;
    }
    std::cout << "Got message: \n" << msg << std::endl;

    return 0;
});
```

### Returns

`None`.

## Fetch one message

Fetches one message in a subscribe loop.

Fetches the next message on the given `@p` channel and / or `@p` channel_group using the context `@p` p, automatically subscribing if there are no messages left in `@p` p. Thus, this might block for a significant time waiting for message(s) to arrive.

`@remark` Changing the `@p` pbsld descriptor during the loop is possible, but your changes may take many iterations of the loop to take effect.

### Method(s)

#### Declaration

`pubnub_res fetch(std::string &o_msg);`

#### Parameters

| Parameter | Description |
| --- | --- |
| `o_msg` *Type: std::string & | String with the fetched message. |

### Sample code

```cpp
std::string msg;
for (;;) {
    enum pubnub_res res = sublup.fetch(msg);
    if (res != PNR_OK) {
        std::cout << "Fetching message failed with code: " << res;
        break;
    }
    std::cout << "Got message: \n" << msg << std::endl;
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_res` | PNR_OK | success (message was fetched). |
|  | other | Indicates the reason for failure. |

## Free a context, with waiting

Tries `pubnub_free()` in a tight loop until either:

1. it succeeds
2. time specified in `@p` millisec elapses

Essentially, it waits for the context to finish its current transaction and then frees it..

This function is much more useful in the callback interface, especially after a [cancel()](#pubnub-cancel)

This function is not useful at all in the sync interface if you're using only one thread with this context.

Also, if you want to do some other processing while waiting for the transaction to finish, don't use this function.

If the context is freed with this member function, it will not be freed in the destructor.

### Method(s)

#### Declaration

`int free_with_timeout(std::chrono::milliseconds duration);`

#### Parameters

| Parameter | Description |
| --- | --- |
| `duration` *Type: std::chrono::milliseconds duration | Max time to wait for freeing to succeed, in milliseconds. |

### Sample code

```cpp
if (0 != ctx.free_with_timeout(std::chrono::milliseconds(1000))) {
    puts("Failed to free the context in due time");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | 0 | `pubnub_free()` succeeded. |
|  | -1 | Failed to `pubnub_free()` in `@p` millisec. |

## Free a context, without waiting

Explicitly frees the context. Mostly provided for completeness, as destructor will also free the context, if needed.

If the context is freed with this member function, it will not be freed in the destructor.

Frees a previously allocated context, if it is not in a transaction. If a context is in a transaction, it will cancel it (as if you called `pubnub_cancel()`), but there's no guarantee that the cancellation will be finished during this call. More precisely, since it is as if you called `pubnub_cancel()`, all semantics of `pubnub_cancel()` apply here, too.

You don't have to free a context when you finish a transaction. Just start a new transaction. Free a context if you're done doing Pubnub transactions for a significant period of time.

### Method(s)

#### Declaration

`int free();`

#### Parameters

This method doesn't take any argument.

### Sample code

```cpp
if (pn.free() != 0) {
    std::cout << "Context not free, cancelation started\n";
}
else {
    std::cout << "Context freed\n";
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | 0 | OK, context freed. |
| `int` | -1 | Context not freed, transaction cancel started. |

## Get the current origin

Gets the origin to be used for the context `p`. If setting of the origin is not enabled, this will return the default origin.

### Method(s)

To `Get the origin` of a Pubnub context use:

```cpp
std::string origin() const
```

### Sample code

#### To get the origin currently set for a context

```cpp
std::cout << "Current origin: " << pn.origin() << std::endl;
```

### Returns

| Type | Description |
| --- | --- |
| `std::string` | The currently used origin for the context |

## Get the transaction timeout

Returns the current transaction timeout for the context.

### Method(s)

To `Get the transaction timeout` you can use the following method(s) in the Posix C++ SDK:

```cpp
std::chrono::milliseconds transaction_timeout_get()
```

### Sample code

#### Get current transaction timeout

```cpp
std::cout <<"Current transaction timeout: " << pn.transaction_timeout_get() << std::endl;
```

### Returns

| Type | Description |
| --- | --- |
| `std::chrono::milliseconds` | Current transaction timeout, in milliseconds (should always be > 0) |

## PubNub cancel

Cancels an ongoing API transaction. This will, once it is done, close the (TCP/IP) connection to Pubnub (if it was open). The outcome of the transaction in progress, if any, will be `#PNR_CANCELLED`.

In the sync interface, it's possible that this cancellation will finish during the execution of a call to this function. But, there's no guarantee, so check the result.

In the callback (async) interface, it's not likely cancellation will be done, but, still, it's possible. So, if this matters to you, it's always best to check the result.

### Method(s)

#### Declaration

`enum pubnub_cancel_res cancel();`

#### Parameters

This method doesn't take any argument.

### Sample code

```cpp
if (PN_CANCEL_FINISHED == pn.cancel()) {
    std::cout << "Cancel done\n";
}
else {
    std::cout << "Cancellation started\n";
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_cancel_res` | PN_CANCEL_STARTED | Cancel started, await the outcome. |
| `enum pubnub_cancel_res` | PN_CANCEL_FINISHED | Cancelled, no need to await. |

## PubNub do not use HTTP keep alive

Disables the use of HTTP Keep-Alive (`persistent connections`) on the context `@p` p.

The default is to `use_` the HTTP Keep-Alive, but, you might want to turn that off - see [use_http_keep_alive()](#pubnub-use-http-keep-alive).

### Method(s)

```cpp
dont_use_http_keep_alive()
```

### Sample code

```cpp
dont_use_http_keep_alive()
```

### Returns

`None`.

## PubNub last HTTP code

Returns the HTTP reply code of the last transaction in the `p` context.

### Method(s)

```cpp
last_http_code()
```

### Sample code

```cpp
res = pn.publish("my_channel", "\"hello\"").await();
if (PNR_OK == res) {
  std::cout <<  pn.last_publish_result() << std::endl;
  std::cout <<  "Last HTTP code: " << pn.last_http_code() << std::endl;
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | HTTP reply code of the last transaction in the `p` context. |

## PubNub leave

Leave the channel. This actually means "initiate a leave transaction". You should leave channel(s) when you want to subscribe to another in the same context to avoid loosing messages. Also, it is useful for tracking presence. You can't leave if a transaction is in progress on the context.

### Method(s)

#### Leave a single channel

```cpp
leave(std::string const &channel, std::string const &channel_group)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: std::string const & | `channel` to invoke a leave event on |
| `channel_group` *Type: std::string const & | `channel group` to invoke a leave event on |

#### Leave multiple channels

```cpp
leave (std::vector< std::string > const &channel, std::vector< std::string > const &channel_group)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: `std::vector <std::string> const &` | channels to invoke a leave event on |
| `channel_group` *Type: `std::vector <std::string> const &` | `channel group` to invoke a leave event on |

### Sample code

```cpp
// Sync
void leave(pubnub::context &pn) {
  enum pubnub_res res;

  res = pn.leave("my_channel", "").await();

  if (PNR_OK == res) {
    std::cout << pn.get() << std::endl;
  } else {
    std::cout << "Request failed" << std::endl;
  }
}

// Lambdas
void leave(pubnub::context &ipn) {
  ipn.leave("my_channel", "").then([=](https://www.pubnub.com/docs/pubnub::context &pn, pubnub_res res) {
    if (PNR_OK == res) {
      std::cout << pn.get() << std::endl;
    } else {
      std::cout << "Request failed" << std::endl;
    }
  });
}

// Functions
void on_leave(pubnub::context &pn, pubnub_res res) {
  if (PNR_OK == res) {
    std::cout << pn.get() << std::endl;
  } else {
    std::cout << "Here Now request failed" << std::endl;
  }
}

void leave(pubnub::context &pn) {
  pn.leave("my_channel", "").then(on_leave);
}
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_res` | `PNR_STARTED` on success, an `error` otherwise |

## PubNub use HTTP keep alive

Enables the use of HTTP Keep-Alive (`persistent connections`) on the context `@p` p.

This is the default, but, you can turn it off with `dont_use_http_keep_alive()`. If HTTP Keep-Alive is active, connection to Pubnub will not be closed after the transaction ends. This will avoid connecting again on next transaction on the same context, making the transaction finish (usually much) quicker. But, there's a trade-off here, here are the drawbacks:

* `dont_use_http_keep_alive()` will not work for contexts that are in `keep alive` state. You need to `pubnub_cancel()` before you can `dont_use_http_keep_alive()`.
* Socket in the keep-alive state will be closed by the PubNub network (server) after some period of inactivity. While we should be able to handle that, it's possible that some race condition causes a transaction to fail in this case.
* Socket in the keep-alive state is `allocated`, consuming some resources. If you have a constrained number of sockets, relative to Pubnub contexts, this may be an issue.

### Method(s)

```cpp
use_http_keep_alive()
```

### Sample code

```cpp
use_http_keep_alive()
```

### Returns

`None`.

## Set blocking IO

Sets the usage of `blocking I/O` for a context. If `blocking I/O` is supported by a platform (it is on most platforms), it will be used, unless some other reason prevents it.

The exact behavior when using `blocking I/O` depends on the platform, but, in general:

* getting (or trying to get) the outcome of a Pubnub transaction will block the caller's thread until the outcome is actually reached.
* if outcome is gotten by polling (calling a Pubnub SDK API to get the outcome), the user will call just once and the poll will return when the outcome is reached (making it impossible for the caller to do anything on that thread until the outcome is reached)
* if outcome is gotten via a callback or similar means, it is most likely that the actual I/O is done non-blocking, but, in any case, user would probably see little difference between blocking and `non-blocking I/O`

In general, `blocking I/O` gives to simpler code, but that scales poorly.

### Method(s)

```cpp
void set_blocking_io(pubnub::blocking_io bio);
```

| Parameter | Description |
| --- | --- |
| `bio` *Type: `pubnub::blocking_io` | Specifies bitwise option: pubnub::blocking, pubnub::non_blocking |

### Sample code

```cpp
pn.set_blocking_io(pubnub::blocking_io);
```

### Returns

`None.`

## Set the transaction timeout

Sets the transaction timeout for the context. This will be used for all subsequent transactions. If a transactions is ongoing and its timeout can be changed, it will be, but if it can't, that would not be reported as an error.

Pubnub SDKs, in general, distinguish the `subscribe` timeout and other transactions, but, C-core doesn't, to save space, as most contexts are either used for `subscribe` or for other transactions.

If timer support is available, context constructor will set a default timeout, which is configurable at compile time. So, if the default timeout is fine with you, you don't have to call this function.

#### Preconditions

* Call this before starting a transaction
* Duration has to be greater than 0

### Method(s)

To `Set the transaction timeout` you can use the following method(s) in the Posix C++ SDK:

```cpp
int set_transaction_timeout(std::chrono::milliseconds duration)
```

| Parameter | Description |
| --- | --- |
| `duration` *Type: std::chrono::milliseconds | Duration of the timeout, in milliseconds |

### Sample code

#### Set the transaction timeout to the default subscribe timeout

```cpp
pn.set_transaction_timeout(std::chrono::seconds(510));
```

### Returns

| Type | Description |
| --- | --- |
| `int` | 0: OK (timeout set), otherwise: error, timers not supported |

## Should a failed transaction be retried

Returns whether retrying a Pubnub transaction makes sense. This is mostly interesting for publishing, but is useful in general. It is least useful for subscribing, because you will most probably subscribe again at some later point in time, even if you're not in a `subscribe loop`.

### Method(s)

`pubnub::tribool should_retry();`

#### Parameters

This method doesn't take any argument.

### Sample code

```cpp
for (i = 0; i < my_retry_limit; ++i) {
    futres futr = ctx.publish(chan, msg);

    futr.await();
    switch (futr.should_retry()) {
        case false:
        break;
        case true:
            Std::cout << "Publishing failed with code: << futr.last_result() << " (" << pubnub_res_2_string(futr.last_result()) >> ")\nRetrying...\n";
        continue;
        default:
            puts("Publish failed, but we decided not to retry");
        break;
    }

    break;
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `pubnub::tribool` | `true` | It's safe to retry, though there is no guarantee that it will help. |
|  | `false` | It doesn't benefit you to re-try the same transaction. |
|  | `pubnub::tribool::not_set` | Retry might help, but, it also can make things worse. For example, for a `#PNR_TIMEOUT`, it may well be that the message was delivered to PubNub, but, the response from PubNub never reached us due to some networking issue, resulting in a timeout. In that case, retrying would send the same message again, duplicating it. |

## Time

This function will return a 17 digit precision Unix epoch.

:::note Algorithm constructing the timetoken
```javascript
timetoken = (Unix epoch time in seconds) * 10000000
```
Example of creating a timetoken for a specific time and date:
```javascript
08/19/2013 @ 9:20pm in UTC = 1376961606
timetoken = 1376961606 * 10000000
timetoken = 13769616060000000
```
:::

### Method(s)

To fetch `Time` you can use the following method(s) in Posix C++ SDK:

```cpp
time()
```

### Sample code

#### Get PubNub timetoken

```cpp
// Sync
void time(pubnub::context &pn) {
  enum pubnub_res res;

  res = pn.time().await();

  if (PNR_OK == res) {
    std::cout << pn.get() << std::endl;
  } else {
    std::cout << "Request failed" << std::endl;
  }
}

// Lambdas
void time(pubnub::context &ipn) {
  ipn.time().then([=](https://www.pubnub.com/docs/pubnub::context &pn, pubnub_res res) {
      if (PNR_OK == res) {
        std::cout << pn.get() << std::endl;
      } else {
        std::cout << "Request failed" << std::endl;
      }
    });
}

// Functions
void on_time(pubnub::context &pn, pubnub_res res) {
  if (PNR_OK == res) {
    std::cout << pn.get() << std::endl;
  } else {
    std::cout << "Request failed" << std::endl;
  }
}

void time(pubnub::context &pn) {
  pn.time().then(on_time);
}
```

### Rest response from server

The `time()` function returns a string timetoken in the following format:

```json

```