Giter Site home page Giter Site logo

idealvin / coost Goto Github PK

View Code? Open in Web Editor NEW
3.8K 129.0 552.0 3.18 MB

A tiny boost library in C++11.

License: Other

Shell 0.02% C 2.42% C++ 91.50% Assembly 4.41% Lua 0.36% CMake 0.49% Dockerfile 0.10% Makefile 0.19% LLVM 0.21% Yacc 0.30%
config coroutine json log rpc unit-test benchmark

coost's People

Contributors

byronhe avatar codehz avatar daidai21 avatar frankhb avatar frederick-vs-ja avatar halft0n avatar hc-tec avatar ichn-hu avatar idealvin avatar izhengfan avatar kuyoonjo avatar leedehai avatar ltmit avatar qixuxiang avatar shihzh avatar shuai132 avatar sn0wywh1te avatar spaceim avatar tigerlee avatar ugotang avatar waruqi avatar zeno-sole avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coost's Issues

`json::Value::str()`不能正确地序列化某些浮点数值

当JSON字符串中含有1.0之类的数值时,json::Value::str()会将其序列化为1,这与原来该字段的类型不符,如果多次依次执行序列化、反序列化操作,会导致断言。

版本:Commit 95535b3 之前都有此现象
系统:Debian 10(Windows未测试)
内核:5.4.0-1-amd64

示例

#include <stdio.h>

#include "base/json.h"

fastring s = "{\"value\": 12.0}";

int main(int argc, char** argv) {
    auto j1 = json::parse(s);
    auto j2 = json::parse(j1.str());

    printf("j1 value: %f\n", j1["value"].get_double());
    printf("j2 value: %f\n", j2["value"].get_double());

    return 0;
}

执行结果

j1[0]: 12.000000
j_test: ./base/json.h:226: double json::Value::get_double() const: Assertion `this->is_double()' failed.
error: execv(/home/tiger/Codes/co/build/linux/x86_64/release/j_test) failed(-1)!

原因:序列化操作使用了fast::dtoa(),而fast::dtoa()在输出浮点时使用了Conversion Specifier g,这会导致尾部的0会被移除。这样就造成了类型不一致的问题。

能否给个CMAKE的编译脚本

能否给个CMAKE的编译脚本,最好在alpine的环境下也能编译通过,github上很多库我在制作alpine镜像时候都碰到各种问题

cannot build with msvc x86

Under co/base/:

$ xmake f -a x86
checking for the Microsoft Visual Studio (x86) version ... 2019

$ xmake
[ 23%]: compiling.release co\impl\epoll.cc
[ 26%]: compiling.release co\impl\co_win.cpp
[ 29%]: compiling.release stack_trace\stack_trace_win.cpp
[ 33%]: compiling.release win\time.cpp
[ 39%]: compiling.release fast.cc
[  6%]: compiling.release fastring.cc
[  9%]: compiling.release hash\base64.cc
[ 16%]: compiling.release co\impl\co_unix.cc
[ 19%]: compiling.release json.cc
[ 42%]: compiling.release co\impl\scheduler.cc
[ 46%]: compiling.release unix\time.cc
[ 49%]: compiling.release win\os.cpp
[ 52%]: compiling.release str.cc
error: time.cpp
C:\Users\fzheng\source\repos\co\base\win/atomic.h(46): error C3861: '_InterlockedIncrement64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(62): error C3861: '_InterlockedDecrement64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(78): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(94): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(110): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(126): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(142): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(158): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(174): error C3861: '_InterlockedOr64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(190): error C3861: '_InterlockedAnd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(206): error C3861: '_InterlockedXor64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(222): error C3861: '_InterlockedOr64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(238): error C3861: '_InterlockedAnd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(254): error C3861: '_InterlockedXor64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(270): error C3861: '_InterlockedExchange64': identifier not found

Lru 实现

插入发现存在是不是调整一下位置到头部?
list用了2个使用一个效率会更好一点?
//一般插入实现大致这样

void put(const Key& key,const Value& value){
	const auto iter = _cache.find(key);
	if(iter!= _cache.end()){
		// 找到了就更新value,并提取到最前面
		iter->second->value = value;
		//move iter->second to _keys' begin postion
		_keys.splice(_keys.begin(),_keys,iter->second);
		return;
	}
	_keys.emplace_front(key,value);
	_cache[key] = _keys.begin();
	resize();
}

是否有意向将install后的库名以及目录名由base改为co?

目前执行xmake install后,会将头文件放在base目录下,静态库被命名为libbase.abase这个名字太普通了,不够将库与程序内部的名字区分开。既然项目名叫co,何不将头文件放在include/co目录下,且库名为libco.alibco.so

这个动静有点大,但从长远来看,我觉得有必要来执行这个改动。

dtoa很慢

做了一个测试,发现对于double类型转为字符串,速度超级慢

const size_t N = 10000000;

template<typename T>
void benchPrintf(const char* fmt) {

    TimeStamp start = TimeStamp::now();
    char buf[32];
  
    for (size_t i = 0; i < N; ++i)
        snprintf(buf, sizeof buf, fmt, (T)(i));

    TimeStamp end = TimeStamp::now();
    printf("benchPrintf %f\n", timeDifference(end, start));
}

template<typename T>
void benchStringStream() {

    TimeStamp start = TimeStamp::now();
    std::ostringstream os;

    for (size_t i = 0; i < N; ++i) {
        os << (T)(i);
        os.seekp(0, std::ios_base::beg);
    }

    TimeStamp end = TimeStamp::now();
    printf("benchStringStream %f\n", timeDifference(end, start));
}

template<typename T>
void benchStream() {

    TimeStamp start = TimeStamp::now();
    FStream os;
    for (size_t i = 0; i < N; ++i) {
        os << (T)(i);
        os.clear();
    }
    TimeStamp end = TimeStamp::now();
    printf("benchStream %f\n", timeDifference(end, start));
}

int main()
{

  puts("int");
  benchPrintf<int>("%d");
  benchStringStream<int>();
  benchStream<int>();

  puts("double");
  benchPrintf<double>("%.12g");
  benchStringStream<double>();
  benchStream<double>();

  puts("int64_t");
  benchPrintf<int64_t>("%" PRId64);
  benchStringStream<int64_t>();
  benchStream<int64_t>();

  puts("void*");
  benchPrintf<void*>("%p");
  benchStringStream<void*>();
  benchStream<void*>();
}

关于LruMap的疑问

// The key is not inserted if it already exists.
void insert(const K& key, const V& value) {
      auto r = _kv.insert(std::make_pair(key, value));
      if (!r.second) return;

      _kl.push_front(key);
      _ki[key] = _kl.begin();

      if (_kv.size() > _capacity) {
          K k = _kl.back();
          _kl.pop_back();
          _kv.erase(k);
          _ki.erase(k);
      }
}

当缓存中已有key时,insert不会有任何操作,如果我想更新一个key的value时该怎么办,并且_kl中的顺序也要改变。

关于 `thread_ptr` 的疑问

@idealvin 你好。

按我的理解,当 thread_ptr 的对象,例如 foo,以 std::ref(foo) 的方式传进线程函数之后,子线程是无法获取父线程设置的指针值的。也就是说,任何一个线程要使用 foo,都必须现在线程内设置 foo 指向的对象才能使用。

既然如此,为什么不在每个线程里分别使用 std::unique_ptr 呢?使用 thread_ptr 的好处在哪里?

Error: Unrecognized Exception

将co log编入dll,使用c#调用,.log文件中会缺失很多条log,并且会产生.fatal文件,.fatal文件事例如下:

1216 22:30:33] Error: Unrecognized Exception
D:\Project\co\base\stack_trace\StackWalker.cpp (1096): StackWalker::ShowCallstack
D:\Project\co\base\stack_trace\stack_trace_win.cpp (203): `anonymous namespace'::StackTraceImpl::on_exception
00007FFBA96B78D8 (ntdll): (filename not available): RtlInitializeCriticalSection
00007FFBA965D4FA (ntdll): (filename not available): RtlWalkFrameChain
00007FFBA965BE9A (ntdll): (filename not available): RtlRaiseException
00007FFBA671A388 (KERNELBASE): (filename not available): RaiseException
00007FFB54122413 (mono-2.0-bdwgc): (filename not available): mono_native_thread_set_name
00007FFB541D3B60 (mono-2.0-bdwgc): (filename not available): mono_thread_set_manage_callback
00007FFB541DC685 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D57E8 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D5576 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFBA8134034 (KERNEL32): (filename not available): BaseThreadInitThunk
00007FFBA96C3691 (ntdll): (filename not available): RtlUserThreadStart

1216 22:30:33] Error: Unrecognized Exception
D:\Project\co\base\stack_trace\StackWalker.cpp (1096): StackWalker::ShowCallstack
D:\Project\co\base\stack_trace\stack_trace_win.cpp (203): `anonymous namespace'::StackTraceImpl::on_exception
00007FFBA96B78D8 (ntdll): (filename not available): RtlInitializeCriticalSection
00007FFBA965D4FA (ntdll): (filename not available): RtlWalkFrameChain
00007FFBA965BE9A (ntdll): (filename not available): RtlRaiseException
00007FFBA671A388 (KERNELBASE): (filename not available): RaiseException
00007FFB54122413 (mono-2.0-bdwgc): (filename not available): mono_native_thread_set_name
00007FFB541D3B60 (mono-2.0-bdwgc): (filename not available): mono_thread_set_manage_callback
00007FFB541D8B0B (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541DB231 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D57E8 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D5576 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFBA8134034 (KERNEL32): (filename not available): BaseThreadInitThunk
00007FFBA96C3691 (ntdll): (filename not available): RtlUserThreadStart

windows 上 dll 调试模式下程序崩溃,Debug Assertion Failed!

只要我使用 co::sleep 函数就会报错
co 使用cmake 编译得 然后引入了 头文件 和LIB文件
使用官方的 client 代码示例

`

sock_t fd = co::tcp_socket();
struct sockaddr_in addr;
co::init_ip_addr(&addr, "127.0.0.1", 7788);
co::connect(fd, &addr, sizeof(addr), 3000);
co::set_tcp_nodelay(fd);
char buf[8] = { 0 };
for (int i = 0; i < 7; ++i) {
    co::sleep(1000);
    LOG << "send ping";
    co::send(fd, "ping", 4);
    co::recv(fd, buf, 4);
    LOG << "recv " << buf;
}
co::close(fd);

`

co::connect 填写第4个参数会报错 崩溃
co::sleep 也会报错 崩溃

错误提示
Debug Assertion Failed!

Program: E:\fiber\exiecheng\coroutine\Debug\testdll.exe
File: D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.26.28801\include\xtree
Line: 229

Expression: map/set iterators incompatible

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

udpsocket co::close无法让co::recvfrom跳出等待

co::close 触发了del_event(ev)
但是co::recvfrom等待的EV_read 消息订阅被删除,但是recvfrom仍然在等待。

解决方法:
1、或许可以加入EV_close/EV_ignore之类的事件。
2、IoEvent加入多事件绑定,同时绑定EV_read和EV_close/EV_ignore。

Question about set_cloexec

inline void set_cloexec(sock_t fd) {
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_EXCL);
}

O_EXCL or FD_CLOEXEC ?

JSON实现不符合ECMA-404

string没有实现\uxxxx形式的unicode转义,以及\b \f的转义。

看实现实在没法看出来为什么会比rapidJSON性能高,而rapidJSON甚至都用上了SIMD优化,麻烦给出benchmark?

rpc test失败

环境:vs2019
问题:运行rpc test程序时出现错误map/set iterators incompatible

fastring: 多线程问题与内存管理问题

  1. fastring 类的引用计数未使用原子对象。这显然会造成多线程同时修改时的数据竞争。希望作者注明这种设计是否有意的。
  2. fastring 类的内存分配、释放函数是不能替换的。我认为替换全局的 operator newoperator delete 是在一定应用条件下提高性能的做法,但 fastring 并不能从中受益。

co:Event wait()不带参数,无法唤醒

#include "co/co.h"
#include "co/log.h"
#include "co/time.h"

co::Event ev;

DEF_bool(wait_alway, true, "false: wait for timeout, true wait alway");
void f2(){
    CLOG << "f2() start";
    bool r = true;
    if (FLG_wait_alway) {
        ev.wait();
    } else {
        r = ev.wait(1*1000);
    }
    CLOG << "f2() end: " << r;
}

void f3() {
    CLOG << "f3() start";
    ev.signal();
    CLOG << "f3() end";
}

int main(int argc, char** argv) {
    flag::init(argc, argv);
    log::init();
    go(f2);
    sleep::ms(100);
    go(f3);

    sleep::ms(2*1000);
    return 0;
}

运行结果1:
./test wait_alway=false

f2() start
f3() start
f3() end
f2() end: true

运行结果1:
./test wait_alway=true

f2() start
f3() start
f3() end

random.h中的一些疑惑

uint32_t next() {
static const uint32_t M = 2147483647L; // 2^31-1
static const uint64_t A = 16385; // 2^14+1

// Computing _seed * A % M.
uint64_t p = _seed * A;
_seed = static_cast<uint32_t>((p >> 31) + (p & M));
if (_seed > M) _seed -= M;

return _seed;
}

其中if (_seed > M) _seed -= M; 这行是不是多余的, 因为M本来就是uint32_t的最大值, 上面一行强转uint32_t之后不能大于M, if这条语句是不可能走到的

如何更改配置的值

类似于文档的这种 日志输出的位置,日志文件名字,应该如何设置呢?

`//日志打印输出的位置
DEF_string(log_dir, "../log", "Log dir, will be created if not exists");
//日志文件名
DEF_string(log_file_name, "acl_log", "name of log file, using exename if empty");
//日志打印级别
DEF_int32(min_log_level, 0, "write logs at or above this level, 0-4 (debug|info|warning|error|fatal)");
//输出到终端
DEF_bool(cout, true, "also logging to terminal");

DEF_int32(co_sched_num, 100, "协程栈大小,每个调度线程都会分配一个栈,调度线程内的协程共用这个栈。");
DEF_int32(co_max_recv_size, 2, "一次能接收的最大数据长度,默认为 1M,超过此大小,分批接收。");
DEF_int32(co_max_send_size, 2, "一次能发送的最大数据长度,默认为 1M,超过此大小,分批发送");`

arm gcc编译器无法通过编译, 需要将char 改成int8_t

index 9d2a6e3..c09f622 100644
--- a/src/hash/base64.cc
+++ b/src/hash/base64.cc
@@ -3,7 +3,7 @@
static const char* entab =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

-static const char detab[256] = {
+static const int8_t detab[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,

fastring 的原位构造函数

现版本的 fastring 拥有直接利用未被管理的内存的构造函数。看起来此构造函数得到使用的地方看起来很少(目前只注意到此处),而且写法上没有体现原位构造的特征。

我个人认为把它改成 static 成员函数(如 fastring::from_raw_buffer )或者友元自由函数(如 friend raw_buffer_to_fastring )会让用户更谨慎而安全地使用。

另外,或许只把此功能作为内部实现而非作为公开 API 也是一种选择。

Document that fastring is not thread-safe

The implementation of fastring is not thread-safe. That’s fine, but people might get in trouble if they don’t know this, since std::string is thread-safe. So it would be good to point this out in the documentation.

(Making fastring thread safe is probably not a good idea. I’ve read that std::string used to use ref-counting and copy-on-write the way yours does, but the atomic operations or mutexes needed to make it thread-safe hurt performance a lot, and it’s actually faster for it to always copy.)

release下执行vs2015 logTest文件报错

FLOG << "This is FLOG (fatal).. " << 23;
执行这句的时候报错
0x00007FFFD0CCE91E (ucrtbase.dll) (**.exe 中)处有未经处理的异常: 请求了严重的程序退出。
想问下是什么情况导致的?
代码和设置没有做任何更改

关于定长整数类型

本库引入了定长整数类型别名。但有一些处理让我觉得困惑:

  • fastring 的内部引用计数类需要假定
    unsigned int 的长度;
  • Random 的整个操作看起来需要依赖标准整数类型的长度;
  • 以及可能存在的其他依赖标准整数类型长度的实现。

这些地方是不是直接使用定长整数类型别名更好?

其次,本库的定长整数类型依赖了 <stdint.h> 。它是 C99/C++11 起的标准库头文件,即使 MSVC 也支持。
是否考虑在此方面移除对 _MSC_VER 的检测?

关于 C++11 特性的考虑

目前看来这些代码并没有按照 C++11 前和 C++11 开始条件编译。假如这是有意的,那么我认为有些细节实现应当继续改进:

  • def.h 应当直接使用 <cstdint> 或者 <stdint.h> 。其他代码应该直接使用 (u)intN_t 以减少冲突。
  • 应该使用标准的 thread_local 代替 __thread
  • 原子对象应当使用 <atomic>
  • swap 函数和移动特殊成员函数应当加上 noexcept
    (以及其他可能存在的问题)

关于Json::Value::operator[]的疑问

https://github.com/idealvin/co/blob/110eadde2c89dffa259a161c100cd4161253441f/base/json.cc#L15

正常访问一个objectmember时,应该先调用has_member()来进行判断。但看上面函数的代码,如果直接使用[]来访问相关member,这里的逻辑似乎是打算支持这种行为?

如果不支持的话,21&22行的意义何在呢?
如果支持的话,接下来访问其它member或者调用str()就会出错了。如以下代码:

#include "co/json.h"

int main() {
  auto v = json::parse("{\"name\": \"tiger\"}");
  v["n"];
  printf("%s\n", v["name"].str().c_str());
  return 0;
}

输出结果是null

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.