path_storage的设计思想

Now it‘s all about path_storage and the internal containers. I‘ve got fair 
criticism that it was too expensive to create many path_storage objects. 
Each of them allocated memory for at least 256 vertices. That‘s true and in 
certain cases it caused huge memory overhead.

Now I separated the path_storage functionality from used containers so that, 
you can use std::vector or std::deque if you wish. Now path_storage is 
declared as:

typedef path_base<vertex_block_storage<double> > path_storage;

And it has exactly the same functionality and behaviour as the former 
path_storage. But now it‘s  much more flexible.

path_base is just a wrapper over some vertex container that provides 
traditional path interface (move_to/line_to/etc) and the VertexSource 
interface.

vertex_block_storage is what was embedded in the path_storage. Now it‘s a 
template:

    template<class T, unsigned BlockShift=8, unsigned BlockPool=256>
    class vertex_block_storage
    . . .

It means you can use floats or even integers for coordinates. Besides, you 
can change the block size. For example:
It means you can use floats or even integers for coordinates. Besides, you 
can change the block size. For example:

typedef path_base<vertex_block_storage<float, 4, 16> > path_storage;
will allocate memory for 16 vertices in floats and 16 pointers.

But it‘s not only that. You can use any available container:

    struct vertex
    {
        typedef float value_type;
        float x,y;
        unsigned cmd;
        vertex() {}
        vertex(float x_, float y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) 
{}
    };

typedef path_base<vertex_stl_storage<std::vector<vertex> > > path_storage;

Here std::vector<vertex> will be used. vertex_stl_storage is an adaptor that 
provides the necessary functionality for path_base.

The container must be compatible with random access STL one (std::list won‘t 
work) and have the following traits:
typedef "vertex_type" value_type;
void clear();
void push_back(vertex_type);
vertex_type& operator [] (unsigned idx);

I have modified the internal AGG containers so that they are compatible with 
STL too. You can use:

typedef path_base<vertex_stl_storage<pod_bvector<vertex> > > path_storage;

The main difference between vertex_block_storage and vertex_stl_storage is 
in memory allocation strategy. vertex_block_storage is compact, but has 
constant memory overhead of at most 1<<BlockShift vertices. Also, it never 
reallocates memory, it only allocates new blocks of a constant size. But 
it‘s not a good idea to create thousands of path_storage objects, because 
that very "constant memory overhead" becomes significant.

On the other hand you can use

    struct vertex
    {
        double x,y;
        unsigned char cmd;
    };
and std::vector<vertex>. But there is another problem. Struct vertex is 
aligned to the size of double and in general there‘s no way to avoid it. It 
means that instead of 17 bytes (8+8+1) it will have sizeof(vertex)=24. If 
you have one million vertices stored in one path, the difference becomes 
significant: 17 megs or 24 megs - it‘s about 40%. In this case it‘s much 
better to use vertex_block_storage and increase the block size:

vertex_block_storage<double, 12>

Here we will have blocks of 1<<12=4096 vertices.

The bottom line is. If you want to create one path_storage with huge number 
of vertices it‘s better to use vertex_block_storage.
If you want to create many objects with just few vertices it‘s better to use 
vertex_stl_storage adaptor.
But there‘s no universal solution, it all depends on the container. Well, 
you can also write your own container.

Also, there‘s a way to use a very lightweight container that will not 
allocate any memory in heap:

        // Here we declare a very cheap-in-use path storage.
        // It allocates space for at most 20 vertices in stack and
        // never allocates memory. But be aware that adding more than
        // 20 vertices is fatal!
        //------------------------
        typedef agg::path_base<
            agg::vertex_stl_storage<
                agg::pod_auto_vector<
                    agg::vertex_d, 20> > > path_storage_type;
        path_storage_type path;

pod_auto_vector allocates memory in stack and if you are absolutely sure you 
never add more than 20 vertices you can use it. It can be important in some 
wrappers for basic shapes that expose the VertexSource interface.

It‘s all may be important in embedded programming, for example.
=========================
Another change is with add_path. It was very confusing. Now there‘re are two 
functions:

concat_path(path, path_id);
join_path(path, path_id);

The first one just adds the path "as is" and it‘s equivalent to former 
add_path(path, 0, false); The second one joins the vertices, that is, 
continues the path ignoring "move_to" commands. It works as if you had a 
protter with broken pen mechanism and the pen was always down. Besides, 
join_path removes the first vertex if it coincides with the last one in the 
existing path. It‘s important in "arc_to" Stephan noticed.

Both functions are important and thre was some confusion.

Also, I have added some utility classes:
poly_plain_adaptor
line_adaptor

It‘s not that considerable, but might be useful in some cases. For example,
methods concat_poly and join_poly use this poly_plain_adaptor internally.

=============================
Renames:
I have renamed container classes.

pod_deque -> pod_bvector

Deque is a neologism that refers to "Double End QUEue". agg::pod_deque was a 
container that was organized in a similar way as std::deque, but it hadn‘t 
method push_front. So, it‘s just a block container that never reallocates 
memory. There‘s no analog in STL.

Other renames:
pod_array -> pod_vector
pod_heap_array -> pod_array

And added pod_auto_vector.
The difference between "vector" and "array" is that vector requires to call 
add(element) to increase the size (std::vector-like behaviour). "array" has 
always constant size and it basically is a simple wrapper over memory 
allocation.
Note: I don‘t want to discuss "reinventing the wheel" issues. Mostly because 
STL doesn‘t have adequate containers. BOOST has them, but it‘s not a 
standard. BOOST is the last resort for AGG. As soon as AGG depends on BOOST 
you can bury it. :-)

==============================

Qestions:
1. I don‘t like name path_base. Could you suggest some other one?
2. path_storage is defined as it was before (same behaviour and 
functionality). I feel there can be several different pre-defined 
(typedefed) storages. Please suggest some. It also makes sense to rename 
path_storage. What would be the best name for a "path storage that allocates 
memory in blocks of 256 vertices and keeps data compact"?
3. Do you feel comfortable with concat_path/join_path?
4. Any other suggestions about all that stuff?
时间: 2024-08-03 17:42:29

path_storage的设计思想的相关文章

中文翻译为&quot;具象状态传输&quot;的RESTful的架构风格和设计思想

本文标签:  具象状态传输 RESTful架构 RESTful理解 REST   服务器 REST 定义了一组体系架构原则,您可以根据这些,包括使用不同语言编写的客户端如何通过 HTTP 处理和传输资源状态.所以在事实上,REST 对 Web的影响非常大,由于其使用相当方便,已经普遍地取代了基于 SOAP 和 WSDL 的接口设计.在多年以后的今天,REST的主要框架已经开始雨后春笋般的出现. REST(Representational State Transfer ),有中文翻译为"具象状态传

作业01的设计思想、程序流程图、源代码、结果截图

一.设计思想: 1.读入类型为String的参数,并且进行显示: 2.然后进行强制类型转化,将String类型转化为int类型: 3.然后各个参数相加: 4.输出最后的结果: 二.流程图: 三.源代码: package demo; public class sum { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println

转:从《The C Programming Language》中学到的那些编程风格和设计思想

这儿有一篇写的很好的读后感:http://www.cnblogs.com/xkfz007/articles/2566424.html 读书不是目的,关键在于思考. 很早就在水木上看到有人推荐<The C Programming Language>这本书,一直都没看,开学一个月就专心拜读了一下,并认真做了课后习题.读来收获不少,主要有两点:一是加深了自己对一些基础知识的理 解和感悟:二是从中学到了一些不错的编程风格和设计思想,这些东西虽看起来不起眼但细细嚼来还是很值得学习的.下面就从四个方面做一

Linux/Unix设计思想

Mike Gancarz 1.Unix开发基于Multics分时操作系统 2.NIH(Not invented here,非我发明) 3.GPL:GUN公共授权协议,适用于软件的法律协议.开源 4.Unix哲学: 1)小即是美:易理解.维护.低消耗系统资源.易于其他工具结合 2)让每一个程序制作好一件事 3)尽快建立原型(prototyping):"第三个系统"概念 4)舍高效而取可移植性 5)使用纯文本文件来存储数据:二进制严格禁止 6)充分利用软件的杠杆效应:借用代码模块;将一切自

把握linux内核设计思想系列(未完待续......)

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 把握linux内核设计思想(一):系统调用 把握linux内核设计思想(二):硬中断及中断处理 把握linux内核设计思想(三):下半部机制之软中断 把握linux内核设计思想(四):下半部机制之tasklet 把握linux内核设计思想(五):下半部机制之工作队列及几种机制的选择 把握linux内核设计思想(六):内核时钟中断 把握linux内核设计思想(七):内核定时器和

kafka入门二:Kafka的设计思想、理念

本节主要从整体角度介绍Kafka的设计思想,其中的每个理念都可以深入研究,以后我可能会发专题文章做深入介绍,在这里只做较概括的描述以便大家更好的理解Kafka的独特之处.本节主要涉及到如下主要内容: Kafka设计基本思想 Kafka中的数据压缩 Kafka消息转运过程中的可靠性 Kafka集群镜像复制 Kafka 备份机制 一.kafka由来 由于对JMS日常管理的过度开支和传统JMS可扩展性方面的局限,LinkedIn(www.linkedin.com)开发了Kafka以满足他们对实时数据流

React的设计思想——理解JSX和Component

基于HTML的前端界面开发正变得越来越复杂,其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上.而来自Facebook的React框架正是完全面向此问题的一个解决方案.React带来了很多开创性的思路来构建前端界面,虽然选择React的最重要原因之一是性能,但是相关技术背后的设计思想更值得我们去思考. React项目经理Tom Occhino曾经阐述React诞生的初衷,他提到React最大的价值究竟是什么?是高性能虚拟DOM.服务器端Render.

Java之------单机版书店管理系统(设计思想和设计模式系列六)销售模块

书店管理系统 书店管理系统可以说是设计模式及设计思想的一个比较经典的例子. 本系列将分为多个部分讲述此输电管理系统. 书店管理系统将分为:用户.图书.进货.销售和库存五个模块,另外还有公共包.工具包和登录包,另外还有一个框架. 对于分层设计,都是表现层可以调用逻辑层,逻辑层调用数据层,数据层调用工具和公共包,方向不可打乱,必须严格按照这种模式. 本篇将做销售模块. 注:本篇需要使用到的框架在本系列二的用户模块: 链接:http://blog.csdn.net/x121850182/article

《Spring设计思想》AOP实现原理(基于JDK和基于CGLIB)

0.前言 在上篇文章<Spring设计思想>AOP设计基本原理中阐述了Spring AOP 的基本原理以及基本机制,本文将深入源码,详细阐述整个Spring AOP实现的整个过程. 读完本文,你将了解到: 1.Spring内部创建代理对象的过程 2.Spring AOP的核心---ProxyFactoryBean 3.基于JDK面向接口的动态代理JdkDynamicAopProxy生成代理对象 4.基于Cglib子类继承方式的动态代理CglibAopProxy生成代理对象 5.各种Advice