函数块(加锁->取出)->调用

本文介绍了一种使用 std::lock_guard 加锁机制来提高数据处理效率的方法。通过预先加锁并缓存数据,使得后续的数据调用不再需要重复加锁,从而达到提升性能的目的。
ObjectList local;
{
    std::lock_guard<std::mutex> lock(mutex_);
    for (auto& obj : objects_) {
        local.emplace_back(obj);
    }
}

if (!local.empty()) {
  for (auto& obj : local) {
    (*obj)(args...);
  }
}

加锁时,快速取出数据。调用是,数据在本地,不用加锁,快速调用。

#include "stream_decoder.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <curl/curl.h> #include <mpg123.h> #include <stdarg.h> #include <time.h> #include <stdint.h> #include <unistd.h> #include <signal.h> // 数据块结构 struct data_chunk { unsigned char *data; size_t size; struct data_chunk *next; }; // 数据队列 struct data_queue { struct data_chunk *head; struct data_chunk *tail; pthread_mutex_t mutex; pthread_cond_t cond; size_t total_size; int finished; }; // 解码器状态 struct StreamDecoder { mpg123_handle *mh; pthread_mutex_t mutex; int stop_requested; // 停止请求标志 int channels; long rate; PCMCallback pcm_callback; void* callback_userdata; LogLevel log_level; pthread_t download_tid; pthread_t decode_tid; struct data_queue queue; CURL *curl; }; // 内部日志函数 static void decoder_log(StreamDecoder *decoder, LogLevel level, const char *format, ...) { if (!decoder || level > decoder->log_level) return; const char *level_str = "DEBUG"; switch(level) { case LOG_LEVEL_ERROR: level_str = "ERROR"; break; case LOG_LEVEL_WARNING: level_str = "WARN"; break; case LOG_LEVEL_INFO: level_str = "INFO"; break; default: break; } va_list args; fprintf(stderr, "[DECODER %s] ", level_str); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } // 初始化队列 static void queue_init(struct data_queue *q) { q->head = q->tail = NULL; pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cond, NULL); q->total_size = 0; q->finished = 0; } // 向队列添加数据 static void queue_push(struct data_queue *q, unsigned char *data, size_t size) { if (!q || !data || size == 0) return; struct data_chunk *chunk = malloc(sizeof(struct data_chunk)); if (!chunk) return; chunk->data = malloc(size); if (!chunk->data) { free(chunk); return; } memcpy(chunk->data, data, size); chunk->size = size; chunk->next = NULL; pthread_mutex_lock(&q->mutex); if (q->tail) { q->tail->next = chunk; } else { q->head = chunk; } q->tail = chunk; q->total_size += size; pthread_cond_signal(&q->cond); pthread_mutex_unlock(&q->mutex); } // 标记队列完成 static void queue_finish(struct data_queue *q) { if (!q) return; pthread_mutex_lock(&q->mutex); q->finished = 1; pthread_cond_signal(&q->cond); pthread_mutex_unlock(&q->mutex); } // 从队列获取数据 static struct data_chunk *queue_pop(struct data_queue *q) { if (!q) return NULL; pthread_mutex_lock(&q->mutex); while (!q->head && !q->finished && !q->stop_requested) { pthread_cond_wait(&q->cond, &q->mutex); } if (!q->head) { pthread_mutex_unlock(&q->mutex); return NULL; } struct data_chunk *chunk = q->head; q->head = chunk->next; if (!q->head) q->tail = NULL; q->total_size -= chunk->size; pthread_mutex_unlock(&q->mutex); return chunk; } // 清理队列 static void queue_cleanup(struct data_queue *q) { if (!q) return; pthread_mutex_lock(&q->mutex); struct data_chunk *chunk = q->head; while (chunk) { struct data_chunk *next = chunk->next; free(chunk->data); free(chunk); chunk = next; } q->head = q->tail = NULL; q->total_size = 0; pthread_mutex_unlock(&q->mutex); } // CURL写入回调 static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct data_queue *q = (struct data_queue *)userp; queue_push(q, (unsigned char *)contents, realsize); return realsize; } // 应用抖动处理 static void apply_dither(short *output, float *input, size_t samples) { const float scale = 32767.0f; for (size_t i = 0; i < samples; i++) { float sample = input[i]; float dither_val = (rand() / (float)RAND_MAX) * 0.0001f; sample += dither_val; if (sample > 1.0f) sample = 1.0f; if (sample < -1.0f) sample = -1.0f; output[i] = (short)(sample * scale); } } // 解码线程 static void* decode_thread(void *arg) { StreamDecoder *decoder = (StreamDecoder *)arg; if (!decoder) return NULL; struct data_queue *q = &decoder->queue; float *buffer = NULL; size_t buffer_size = 8192 * sizeof(float); size_t done; int status; // 分配音频缓冲区 if (posix_memalign((void**)&buffer, 16, buffer_size)) { decoder_log(decoder, LOG_LEVEL_ERROR, "音频缓冲区分配失败"); return NULL; } // 分配PCM输出缓冲区 size_t max_pcm_size = 8192 * sizeof(short) * 2; // 立体声 short *pcm_buffer = malloc(max_pcm_size); if (!pcm_buffer) { decoder_log(decoder, LOG_LEVEL_ERROR, "PCM缓冲区分配失败"); free(buffer); return NULL; } srand(time(NULL)); while (1) { // 检查停止标志 pthread_mutex_lock(&decoder->mutex); if (decoder->stop_requested) { pthread_mutex_unlock(&decoder->mutex); break; } pthread_mutex_unlock(&decoder->mutex); struct data_chunk *chunk = queue_pop(q); if (chunk == NULL) { // 没有更多数据 break; } if (mpg123_feed(decoder->mh, chunk->data, chunk->size) != MPG123_OK) { decoder_log(decoder, LOG_LEVEL_WARNING, "数据供给失败"); free(chunk->data); free(chunk); continue; } free(chunk->data); free(chunk); while (1) { // 检查停止标志 pthread_mutex_lock(&decoder->mutex); if (decoder->stop_requested) { pthread_mutex_unlock(&decoder->mutex); break; } pthread_mutex_unlock(&decoder->mutex); status = mpg123_read(decoder->mh, (unsigned char*)buffer, buffer_size, &done); // 处理格式变化 if (status == MPG123_NEW_FORMAT) { long rate; int channels, encoding; if (mpg123_getformat(decoder->mh, &rate, &channels, &encoding) == MPG123_OK) { decoder->channels = channels; decoder->rate = rate; decoder_log(decoder, LOG_LEVEL_INFO, "音频格式: %d 声道, %ld Hz", channels, rate); } continue; } // 需要更多数据或错误 if (status == MPG123_NEED_MORE || status != MPG123_OK) { break; } // 处理解码后的PCM数据 if (done > 0) { size_t frames = done / (sizeof(float) * decoder->channels); size_t pcm_size = frames * sizeof(short) * decoder->channels; apply_dither(pcm_buffer, buffer, frames * decoder->channels); if (decoder->pcm_callback) { decoder->pcm_callback(pcm_buffer, pcm_size, decoder->channels, decoder->rate, decoder->callback_userdata); } } } } free(buffer); free(pcm_buffer); decoder_log(decoder, LOG_LEVEL_INFO, "解码线程退出"); return NULL; } // 下载线程 static void* download_thread(void *arg) { StreamDecoder *decoder = (StreamDecoder *)arg; if (!decoder || !decoder->curl) return NULL; decoder_log(decoder, LOG_LEVEL_INFO, "开始下载音频流"); CURLcode res = curl_easy_perform(decoder->curl); if (res != CURLE_OK) { decoder_log(decoder, LOG_LEVEL_ERROR, "下载失败: %s", curl_easy_strerror(res)); } else { decoder_log(decoder, LOG_LEVEL_INFO, "下载完成"); } queue_finish(&decoder->queue); decoder_log(decoder, LOG_LEVEL_INFO, "下载线程退出"); return NULL; } // ================== 公共接口实现 ================== StreamDecoder* stream_decoder_create() { StreamDecoder* decoder = calloc(1, sizeof(StreamDecoder)); if (!decoder) return NULL; // 初始化队列 queue_init(&decoder->queue); // 初始化mpg123 if (mpg123_init() != MPG123_OK) { free(decoder); return NULL; } decoder->mh = mpg123_new(NULL, NULL); if (!decoder->mh) { mpg123_exit(); free(decoder); return NULL; } if (mpg123_format_none(decoder->mh) != MPG123_OK || mpg123_format(decoder->mh, 44100, MPG123_STEREO, MPG123_ENC_FLOAT_32) != MPG123_OK) { mpg123_delete(decoder->mh); mpg123_exit(); free(decoder); return NULL; } if (mpg123_open_feed(decoder->mh) != MPG123_OK) { mpg123_delete(decoder->mh); mpg123_exit(); free(decoder); return NULL; } // 初始化互斥锁 pthread_mutex_init(&decoder->mutex, NULL); // 初始化解码器状态 decoder->stop_requested = 0; decoder->channels = 0; decoder->rate = 0; decoder->pcm_callback = NULL; decoder->callback_userdata = NULL; decoder->log_level = LOG_LEVEL_ERROR; decoder->curl = NULL; return decoder; } void stream_decoder_destroy(StreamDecoder* decoder) { if (!decoder) return; // 停止解码 stream_decoder_stop(decoder); // 清理队列 queue_cleanup(&decoder->queue); // 清理mpg123 if (decoder->mh) { mpg123_close(decoder->mh); mpg123_delete(decoder->mh); } mpg123_exit(); // 销毁互斥锁 pthread_mutex_destroy(&decoder->mutex); free(decoder); } void stream_decoder_set_callback(StreamDecoder* decoder, PCMCallback callback, void* userdata) { if (!decoder) return; decoder->pcm_callback = callback; decoder->callback_userdata = userdata; } void stream_decoder_set_log_level(StreamDecoder* decoder, LogLevel level) { if (!decoder) return; decoder->log_level = level; } int stream_decoder_start(StreamDecoder* decoder, const char* url) { if (!decoder || !url) return 0; decoder_log(decoder, LOG_LEVEL_INFO, "开始解码: %s", url); // 重置状态 pthread_mutex_lock(&decoder->mutex); decoder->stop_requested = 0; decoder->channels = 0; decoder->rate = 0; pthread_mutex_unlock(&decoder->mutex); // 清理队列 queue_cleanup(&decoder->queue); queue_init(&decoder->queue); // 初始化curl curl_global_init(CURL_GLOBAL_DEFAULT); decoder->curl = curl_easy_init(); if (!decoder->curl) { decoder_log(decoder, LOG_LEVEL_ERROR, "无法初始化CURL"); return 0; } // 设置CURL选项 curl_easy_setopt(decoder->curl, CURLOPT_URL, url); curl_easy_setopt(decoder->curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(decoder->curl, CURLOPT_WRITEDATA, &decoder->queue); curl_easy_setopt(decoder->curl, CURLOPT_USERAGENT, "AudioStreamDecoder/1.0"); curl_easy_setopt(decoder->curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(decoder->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(decoder->curl, CURLOPT_CONNECTTIMEOUT, 10L); curl_easy_setopt(decoder->curl, CURLOPT_TIMEOUT, 0L); // 无限超时 // 创建下载线程 if (pthread_create(&decoder->download_tid, NULL, download_thread, decoder) != 0) { decoder_log(decoder, LOG_LEVEL_ERROR, "无法创建下载线程"); curl_easy_cleanup(decoder->curl); curl_global_cleanup(); return 0; } // 创建解码线程 if (pthread_create(&decoder->decode_tid, NULL, decode_thread, decoder) != 0) { decoder_log(decoder, LOG_LEVEL_ERROR, "无法创建解码线程"); pthread_mutex_lock(&decoder->mutex); decoder->stop_requested = 1; pthread_mutex_unlock(&decoder->mutex); pthread_join(decoder->download_tid, NULL); curl_easy_cleanup(decoder->curl); curl_global_cleanup(); return 0; } return 1; } void stream_decoder_stop(StreamDecoder* decoder) { if (!decoder) return; decoder_log(decoder, LOG_LEVEL_INFO, "停止解码"); // 设置停止标志 pthread_mutex_lock(&decoder->mutex); decoder->stop_requested = 1; pthread_mutex_unlock(&decoder->mutex); // 中断CURL下载 if (decoder->curl) { curl_easy_setopt(decoder->curl, CURLOPT_TIMEOUT, 1L); // 设置超时以中断下载 } // 唤醒可能等待的线程 pthread_cond_broadcast(&decoder->queue.cond); // 等待线程结束 pthread_join(decoder->download_tid, NULL); pthread_join(decoder->decode_tid, NULL); // 清理curl if (decoder->curl) { curl_easy_cleanup(decoder->curl); curl_global_cleanup(); decoder->curl = NULL; } // 重置队列 queue_cleanup(&decoder->queue); } gcc -c stream_decoder.c -o stream_decoder.o -I. -lcurl -lmpg123 -lpthread stream_decoder.c: In function ‘queue_pop’: stream_decoder.c:121:42: error: ‘struct data_queue’ has no member named ‘stop_requested’ 121 | while (!q->head && !q->finished && !q->stop_requested) {
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值