windows 接入阿里云oss C SDK, 实现异步下载 的经验和总结

前段时间项目有个需求:游戏中接入自定义头像。

我们项目采用的方案,是把用户自定义的头像存储到阿里云的 oss 上。需要的时候,把头像图片下载到本地,放到游戏引擎能取到的路径,通知游戏下载成功,游戏逻辑端再像操作普通的资源一样,创建用户自定义头像的图片作为精灵使用到游戏里。

iOS端和android端已经由其他同事接入了。但是平时开发时不便于测试,因此需要再在电脑上,对于我来说就是win32平台,也接入 oss 上传和下载的流程。

这周任务不是很多,于是前两天折腾了一下。

OSS 的 官方文档在此:

https://help.aliyun.com/document_detail/32137.html?spm=a2c4g.11186623.6.803.q6Fjje

打开链接,发现有各种语言的SDK,好像很方便的样子。 iOS,android 的都有现成的。win32用哪个呢?往下一翻,看到了 C语言版的,就是它了。

官方的文档很全面,c语言 sdk 下载包里面甚至还有全套的源代码,依赖的第三方库 在 third_party 路径的 include 和 prebuilt  里摆得整整齐齐,接入到工程里还算轻松。整合到项目里,经过一翻调试,上传下载均OK 。

本以为完事大吉。然而此时突然发现:C 语言的 oss 库代码 ,并不支持异步下载。也就是说下载个图片会卡游戏主线程。如果进个排行榜页面,一口气下载50来个自定义图片,卡主线程很久肯定是无法接受的。于是,看了一下 iOS 和 android 的 oss sdk 是怎么解决的。

大概看了一下,发现这两个平台的 SDK 都把异步封装好了,下载时,设置好回调函数就行了。反观 C 语言版的 库,并无如此高级的功能。不过仔细想了一下这也正常:毕竟 C语言标准库 里 好像就没有跟线程相关的内容,只能自己起一个新的线程做异步处理了。

思路大概就是要实现一个简单的“生产者消费者”模型:下载线程负责“生产”用户自定义头像;游戏主线程负责“消费”,取走下载好的用户自定义头像,给游戏逻辑发通知。

有了思路后,开始撸代码。过程中了解和巩固了一些c++相关的知识点,包括c++基础数据结构 std::map std::deque的用法;

c++ 11 的 std::thread 线程库;

std::mutex 做线程间公用数据的 互斥锁

关于 std::mutex  互斥锁,需要再整理一下原理和思路:

线程之间如果想要通信,本质就是交换数据,A线程生产 data,B线程消费data。有生产有消费,同时都在操作 data 这一个数据,就有可能在同时操作  data 时乱套,因此 ,就需要给 data 分配一把 mutex 互斥锁,在不同线程操作 data 时 (包括读和写)的前后, 加好 mutex.lock,mutex.release,保证线程不会出问题。加的时候还要小心一些,防止 互相卡死 造成的线程死锁。

道理很简单,但是如果不亲手多进行实际操作,就很难理解透彻。

思路弄清晰了以后,代码写起来就很快了。

由于自己不是特别明白信号量的用法,因此,消费者(游戏主线程)现在的写法,是在游戏主循环里 采用每帧 轮询的方式,找 生产者(下载线程)上门来索要 下载好的结果。看起来有点 low ,有待改进。

不过不管怎么说,还是实现了需求。

中间还有一些细节,比如  std::map 如何安全地一边遍历,一边删除等等。但是最关键的代码,还是线程的使用,和线程的同步,线程之间的通信。

这部分代码跟其他代码有一些耦合,稍微改一改是能够做到独立的。把关键代码贴在这里,做个备忘,就暂时不追求细节了

OSSManager.h

#ifndef __OSS_MANAGER_H__
#define __OSS_MANAGER_H__

#include <string>
#include "aos_http_io.h"
#include "oss_api.h"
#include "oss_auth.h"
#include "oss_define.h"
#include "oss_util.h"
#include "aos_list.h"
#include "aos_status.h"

#include <map>
#include <mutex>
#include <deque>

namespace oss{
	class OSSDownloadRequest
	{
	public:
		OSSDownloadRequest(std::string objectPath, std::string saveAsPath);

		void markStart(bool bStart){ this->bStarted = bStart; }
		void markSucc(bool bSucc){ this->bSucc = bSucc; }
		void markDone(bool bDone){ this->bDone = bDone; }

		bool i
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值