#include <stdio.h>
#include <iostream>
#include <vector>
#include <boost/pool/singleton_pool.hpp>
#include <boost/pool/pool_alloc.hpp>


template<typename T,  unsigned int NEXT_SIZE = 32U, unsigned int  MAX_POOL_SIZE = 0U>
class CMemoryPoolT
{
public:
     static void* operator new(size_t size)
     {
          return boost::singleton_pool<T,
               sizeof(T),
               boost::default_user_allocator_new_delete,
               boost::details::pool::default_mutex,
               NEXT_SIZE,
               MAX_POOL_SIZE>::malloc();
     }

     static void operator delete(void* p)
     {
          boost::singleton_pool<T,
               sizeof(T),
               boost::default_user_allocator_new_delete,
               boost::details::pool::default_mutex,
               NEXT_SIZE,
               MAX_POOL_SIZE>::free(p);
     }
};


class CMemoryPoolTest  :public CMemoryPoolT<CMemoryPoolTest>
{
public:
     char Dumy[124] ;
};


int _tmain(int argc, _TCHAR* argv[])
{
     using std::vector ;

     CMemoryPoolTest *p = new CMemoryPoolTest() ;

     delete p ;

     printf("Using MemoryPool... \n") ;


     return 0;
}


위와 같이 작성을 하면 아주 편하게 사용할수 있다

 

메모리 풀을 적용하고 싶은 클래스에 CMemoryPoolT을 상속해주고  

템플릿 명시를 자기 클래스 이름으로 적어 놓는다.

 

명시를 하는 이유는 A라는 클래스가 있고 B라는 클래스 있다고 치면 A라는 클래스와 B라는 클래스를 다른 클래스이므로 메모리를 관리 할때 따로 관리 하는게 편하다.

 

따로 관리를 하기위해 태그를 붙이는 거라 생각을 하면 쉽다.

쓸만한게 있으면 계속 업데이트 됩니다. 


Copy as Html 

http://plugins.jetbrains.com/plugin/190

자바 소스 코드를 html로 변경해줍니다. 

블로그나 인터넷 게시판에 html태그로 소스를 보기 좋게 해주기때문에 쓸만한 듯 싶습니다.



'tools > intellij' 카테고리의 다른 글

Intellij 설정  (0) 2014.09.17
intellij 단축키  (0) 2014.09.17

계속 업데이트 예정 

 

1. 주석이나 문자열 스펠링 체크 해제 (주석및 문자열 안의 스펠링 검사 해제)

  설정창 들어가서 검색 'Spellchecker'  체크 해제 

 

2. 이클립스에 비해 인텔리센스가 디폴트 설정도 편하지만 visual studio의  Visual Assist랑 맞먹을려면!!? 

설정창 들어가서  검색 Code Completion 에서 Case sensitive completion  "None"로 변경

 코드 자동완성 발동조건에 대소문자 구분안하게 된다.

-개인적으로 이클립스처럼 Ctrl + Shift 키를 안눌러도 자동으로 발동되는 것이 제일 마음에 든다 -_-;;;

 

3. 띄어쓰기 탭으로 인식 

 설정창 tab으로 검색및 CodeStyle 하부메뉴의 각 언어에서 Use Tab character  및 smart tabs 체크

 

4. 자동 정렬시 한줄당 최고 글자수 설정

  settings에서  right margin 검색

   Project settings -> Code Style -> General -> Right margin 값 설정

 

 

 

 

 

필요에 따라 사용

* 다른 프로젝트에서 소스를 임포트를 했을때 기본 인코딩이 euc-kr일 경우 매소스마다 설정하기가 불편하다

설정창 File Encodings 검색 IDE Encoding 값 변경

 

 

intellij 가이드 링크

http://beyondj2ee.wordpress.com/2013/06/28/%ec%9d%b8%ed%85%94%eb%a6%acj-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-part4-getting-start-intellij-git/

'tools > intellij' 카테고리의 다른 글

Intellij Plugin  (0) 2014.09.17
intellij 단축키  (0) 2014.09.17

Editing
Ctrl + Space Basic code completion (the name of any class,method or variable)
Ctrl + Shift + Space Smart code completion (filters the list of methodsand variables by expected type)
Ctrl + Shift + Enter Complete statement
Ctrl + P  함수호출시 인수 정보 확인 (within method call arguments)
Ctrl + Q  코드에 대한 문서창 팝업
Shift + F1 코드에 대한 문서 인터넷 브라우저로 팝업
Ctrl + mouse  코드를 링크처럼 타고 들어감

Ctrl + F1 Show descriptions of error or warning at caret
Alt + Insert  코드 생성 (Getters, Setters, Constructors,hashCode/equals, toString)
Ctrl + O  메서드 오버라이드 구현

Ctrl + I    인터페이스 메서드 구현
Ctrl + Alt + T  다음으로 코드 감싸기… (if..else, try..catch, for,synchronized, etc.)
Ctrl + / 줄 단위 주석 토글
Ctrl + Shift + /  블럭 단위 주석 토글

Ctrl + W 가장 안쪽의 괄호부터 선택(점점 확장 된다.)

Ctrl + Shift + W Decrease current selection to previous state
Alt + Q Context info
Alt + Enter Show intention actions and quick-fixes
Ctrl + Alt + L  파일 단위 재정렬 (이클립스의 ctrl + shift + f) 
Ctrl + Alt + O import 문 최적화
Ctrl + Alt + I  줄단위 재정렬

Tab / Shift + Tab  들여쓰기/내어쓰기

Ctrl + X or Shift + Delete 잘라내기 (블럭 선택이 안되어 있으면 라인을 잘라냄)
Ctrl + C or Ctrl + Insert 복사하기(블럭 선택이 안되어 있으면 라인을 복사함)
Ctrl + V or Shift + Insert 붙여넣기
Ctrl + Shift + V 복사하기 (목록에서 선택하여)

Ctrl + D 선택된 블럭을 복제
Ctrl + Y 캐럿을 있는 곳의 라인 삭제

Ctrl + Shift + J 스마트하게 코드를 한 줄로 합친다.

Ctrl + Enter 스마트하게 코드를 여러줄로 나눈다.
Shift + Enter 커서가 어디에 있건 다음 라인을 생성하고 첫줄로 이도
Ctrl + Shift + U 커서가 있는 곳이나 블럭이 있는 곳을 대문자 및 소문자로 치화
Ctrl + Shift + ] / [  가장 가까운 괄호 시작/종료로 이동

Ctrl + Delete 단어 삭제 (커서 시작부터)
Ctrl + Backspace Delete to word start
Ctrl + NumPad+/- Expand/collapse code block
Ctrl + Shift + NumPad+ Expand all
Ctrl + Shift + NumPad- Collapse all
Ctrl + F4 Close active editor tab

 

 

Double Shift Search everywhere
Ctrl + F Find
F3 Find next
Shift + F3 Find previous
Ctrl + R Replace
Ctrl + Shift + F Find in path
Ctrl + Shift + R Replace in path
Ctrl + Shift + S Search structurally (Ultimate Edition only)
Ctrl + Shift + M Replace structurally (Ultimate Edition only)

 

 

 

Usage Search
Alt + F7 / Ctrl + F7 Find usages / Find usages in file
Ctrl + Shift + F7 Highlight usages in file
Ctrl + Alt + F7 Show usages

 

 

Compile and Run
Ctrl + F9 Make project (compile modifed and dependent)
Ctrl + Shift + F9 Compile selected file, package or module
Alt + Shift + F10 Select configuration and run
Alt + Shift + F9 Select configuration and debug
Shift + F10 Run
Shift + F9 Debug
Ctrl + Shift + F10 Run context configuration from editor

 

Debugging
F8 Step over
F7 Step into
Shift + F7 Smart step into
Shift + F8 Step out
Alt + F9 Run to cursor
Alt + F8 Evaluate expression
F9 Resume program
Ctrl + F8 Toggle breakpoint
Ctrl + Shift + F8 View breakpoints

 

 

Navigation
Ctrl + N Go to class
Ctrl + Shift + N Go to file
Ctrl + Alt + Shift + N Go to symbol
Alt + Right/Left Go to next/previous editor tab
F12 Go back to previous tool window
Esc Go to editor (from tool window)
Shift + Esc Hide active or last active window
Ctrl + Shift + F4 Close active run/messages/find/... tab
Ctrl + G Go to line
Ctrl + E Recent files popup
Ctrl + Alt + Left/Right Navigate back/forward
Ctrl + Shift + Backspace Navigate to last edit location
Alt + F1 Select current file or symbol in any view
Ctrl + B or Ctrl + Click Go to declaration
Ctrl + Alt + B Go to implementation(s)
Ctrl + Shift + I Open quick definition lookup
Ctrl + Shift + B Go to type declaration
Ctrl + U Go to super-method/super-class
Alt + Up/Down Go to previous/next method
Ctrl + ] / [ Move to code block end/start
Ctrl + F12 File structure popup
Ctrl + H Type hierarchy
Ctrl + Shift + H Method hierarchy
Ctrl + Alt + H Call hierarchy
F2 / Shift + F2 Next/previous highlighted error
F4 / Ctrl + Enter Edit source / View source
Alt + Home Show navigation bar
F11 Toggle bookmark
Ctrl + F11 Toggle bookmark with mnemonic
Ctrl + #[0-9] Go to numbered bookmark
Shift + F11 Show bookmarks

 

 

 

Refactoring
F5 Copy
F6 Move
Alt + Delete Safe Delete
Shift + F6 Rename
Ctrl + F6 Change Signature
Ctrl + Alt + N Inline
Ctrl + Alt + M Extract Method
Ctrl + Alt + V Extract Variable
Ctrl + Alt + F Extract Field
Ctrl + Alt + C Extract Constant
Ctrl + Alt + P Extract Parameter

 

 

 

VCS/Local History
Ctrl + K Commit project to VCS
Ctrl + T Update project from VCS
Alt + Shift + C View recent changes
Alt + BackQuote (`) ‘VCS’ quick popup

 

 

Live Templates
Ctrl + Alt + J Surround with Live Template
Ctrl + J Insert Live Template
iter Iteration according to Java SDK 1.5 style
inst Check object type with instanceof and downcast it
itco Iterate elements of java.util.Collection
itit Iterate elements of java.util.Iterator
itli Iterate elements of java.util.List
psf public static final
thr throw new

 


General
Alt + #[0-9] Open corresponding tool window
Ctrl + S Save all
Ctrl + Alt + Y Synchronize
Ctrl + Shift + F12 Toggle maximizing editor
Alt + Shift + F Add to Favorites
Alt + Shift + I Inspect current file with current profile
Ctrl + BackQuote (`) Quick switch current scheme
Ctrl + Alt + S Open Settings dialog
Ctrl + Alt + Shift + S Open Project Structure dialog
Ctrl + Shift + A Find Action
Ctrl + Tab Switch between tabs and tool window

'tools > intellij' 카테고리의 다른 글

Intellij Plugin  (0) 2014.09.17
Intellij 설정  (0) 2014.09.17

개인적으로 boost보다는 ACE를 더 선호 합니다.


개인적으로 boost도 훌륭한 라이브러리라고 생각하지만 너무 심각하게 메타프로그래밍이라.. 

자칫 처음 쓰는 사람들에게는 어렵게 느껴질수 있습니다.

거기에다 ACE에서는 꽤나 실용적인 로직들이 많이 존재합니다.


어차피 gethostbyname으로  도메인의 아이피를 얻을때  해당 도메인에 속해 있는 모든 아이피 목록을 가져 오는 경우는 드뭅니다. 

해당 도메인에 아이피가 하나만 걸려 있거나, 여러개 걸려 있어도 로드밸런싱을 위해 당장 필요한 아이피  하나만 가져와서 씁니다.

 ACE_INET_Addr  google_addr;

 google_addr.set( 80, "google.com");

 strcpy(szServerIP, google_addr.get_host_addr());

참 단순한 로직입니다. 3줄이면 간단하게 아이피를 가져옵니다. 3줄도 많다구요?


 ACE_INET_Addr  google_addr( 80, "google.com");

 strcpy(szServerIP, google_addr.get_host_addr());

더 짧게 하면 두 줄 이군요...


거기다  내부 로직을 살펴 보면 gethostbyname을 쓰지 않고 gethostbyname_r을 사용하고 있습니다. 

즉 Thread Safe하다는 것이죠!



'C++ > ACE' 카테고리의 다른 글

플랫폼 독립적인 설정파일 로딩 로직  (0) 2014.09.16
ACE_dev_pool_reactor 쓰레드 안정성에 대해  (0) 2014.09.16

리눅스 계열이든 윈도우 계열이든 서버 모듈을 개발시  설정 문서에서 값을 읽어오는 건 필수적이다.

윈도우에서 가장 쉽게 쓸수 있는 GetPrivateProfileString는 윈도우에서만 사용을 할 수 있다.

다음 ACE 라이브러리 함수를 사용하면  리눅스든 윈도우든 똑같이 작동을 한다.

 

물론 윈도우에서만 개발 하는 사람들은  소스가 많이 길어지니 불편할듯... 하다.

리눅스 개발자는 이거라도 해주면 고마워 한다..

 

 

#include <ace/OS.h>
#include <ace/Configuration.h>
#include <ace/Configuration_Import_Export.h>

 

int ACE_TMAIN()
{        ACE_Configuration_Heap config ;

        if(config.open() == -1)
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("config open error\n")), -1) ;
        }
               
        ACE_Ini_ImpExp config_importer(config) ;

       
        if(config_importer.import_config("as.conf")== -1)
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("not found conf file\n")), -1) ;
        }
               
       
        ACE_Configuration_Section_Key secion ;
        if(config.open_section(config.root_section(), ACE_TEXT("CONF"), 0, secion) == -1 )
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("secion open error\n")), -1) ;
        }
               
        ACE_TString strData ;

        if(config.get_string_value(secion, ACE_TEXT("result"), strData) == -1  )
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("Get String Value Error\n")), -1) ;
        }                                 
               
       
        printf("%s\n", strData.c_str());
                
        config.remove_section(config.root_section(), ACE_TEXT("CONF"), 0) ;
                
        return 0 ;
}

 

 

 

 

그럼 프로그램에서 읽어들이는 설정 문서 파일의 이름은 as.conf 이고 안에 내용은 다음과 같다.[CONF]
result=  reading conf

 

 

 

결과적으로  프로그램 실행을 했을시 콘솔에 찍히는 내용은 다음과 같다.

 

 reading conf

'C++ > ACE' 카테고리의 다른 글

초간단 도메인으로 IP 주소 얻기  (0) 2014.09.16
ACE_dev_pool_reactor 쓰레드 안정성에 대해  (0) 2014.09.16

 

리눅스에서 ACE를 관련하여 Reactor 패턴을 구현을 할때  대부분 ACE_Dev_poll_Reactor에 관심을

많이 가질것이다.  왜냐 하면 하면  리눅스  2.4 이상의 커널에서 ACE를 빌드를 할때 ACE_HAS_EVENT_POLL 를 추가하면 리눅스에서 IOCP에 필적하는 Epoll을 사용 할 수 있기 때문이다.  물론 IOCP 자체가 Proactor 기반이고 Epoll은 Reactor 기반인지라 비교 하기에는 무리가 있기는 하지만.. 어차피 리눅스 자체가 Reactor에 최적화가 되어 있고 윈도우는 Proactor에 최적화 되어 있는

각 운영체제에서 최고의 효율을 낸다는 사실에서 비견을 할만하다.

 

하지만 ACE_TP_Reactor은 내부적으로 리더/팔로우 패턴으로 쓰레드 풀을 사용 되어 있다고 한다.

 

그런데 ACE_Dev_Poll_Reactor을 확인 하여 보았을때 이 역시 내부적으로 쓰레드풀을 사용하는지

 

아니면  Epoll 관련 함수가 자체적으로 Thread Safe해서인지  TP_Reactor 과 마찬가지로

 

run_reactor_events_loop를  복수의 쓰레드를 통해서 사용되어도 문제가 없는거 같다.

 

 

내부의 Handle_Event 함수도 쓰레드 세이프하게 되어 있고. Owner 내부에서도 사용되지를 않는데

 

마음놓고 TP_Reactor와 똑같은 방식으로 사용을 하면 될 듯 합니다. 

 

또한 구글 검색에서 건졌는데 ACE의 창시자 더글라스 교수님이 친절한 답변도 볼 수 있었습니다 :D

 

Hi Rafi,

> A small question.  May Dev_Poll_Reactor be driven by
> multiple-threads simultaneously, or something like TP_Reactor is
> needed?

You can use multiple threads.  BTW, to ensure that we have proper
version/platform/compiler information, please make sure you fill out
the appropriate problem report form (PRF), which is in

$ACE_ROOT/PROBLEM-REPORT-FORM
$TAO_ROOT/PROBLEM-REPORT-FORM

or in

$ACE_ROOT/BUG-REPORT-FORM
$TAO_ROOT/BUG-REPORT-FORM

in older versions of ACE+TAO.  Make sure to include this information
when asking any questions about ACE+TAO since otherwise we have to
"guess" what version/platform/compiler/options you've using, which is
very error-prone and slows down our responsiveness.  If you don't use
the PRF, therefore, it is less likely that someone from the core
ACE+TAO developer team will be able to answer your question.
Naturally, we encourage and appreciate other members of the ACE+TAO
user community who can respond to questions that they have the answers
to.

Thanks,

        Doug
-- 
Dr. Douglas C. Schmidt                       Professor and Associate Chair
Electrical Engineering and Computer Science  TEL: (615) 343-8197
Vanderbilt University                        WEB: 
www.dre.vanderbilt.edu/~schmidt
Nashville, TN 37203                          NET: d.schmidt@xxxxxxxxxxxxxx

P.S 그런데 ACE 5.7에서  Dev_Pool_Reactor과 관련하여 쓰레드 안정성에 대해 FIX 하였다는 글을 본 적이 있었는데 아무튼.. 왠만하면 Dev_Poll 에서 멀티 쓰레드를 사용할려면 5.7 이상 사용하시는게 좋을 듯 합니다.

'C++ > ACE' 카테고리의 다른 글

초간단 도메인으로 IP 주소 얻기  (0) 2014.09.16
플랫폼 독립적인 설정파일 로딩 로직  (0) 2014.09.16

간단한 TBB  parallel_for  예제  

여기서는 람다를 사용을 하고 있지만...

아직 C++0x가 적용 안된 컴파일러 (Windows의 경우 visual studio 2008 이하) 는 람다 함수를 사용 할 수가 없다.

람다 함수를 사용하는 대신에 functor를 이용 해야 한다.

[-] Collapse  

#include <stdio.h>
#include <tchar.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/atomic.h> // atomic
#include <tbb/mutex.h> // 뮤텍스



#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG



using namespace tbb ;

int main(int argc, _TCHAR* argv[])
{
    task_scheduler_init init ;

    //int nOut = 0 ;
    atomic<int> nOut ;
    nOut  = 0 ;


    parallel_for(blocked_range<int>(0, 100000),
        [&nOut](const blocked_range<int>& iter)
    {
        for (int n = iter.begin() ; n != iter.end() ; ++n)
        {
            nOut += 1 ;
        }
    }
    ,  auto_partitioner()) ;

    printf("Result %d\n", nOut) ;



    // 다른 락거는 방법

    tbb::mutex _lock;
    int   _sum = 0;
    parallel_for(blocked_range<int>(0, 100000),
        [&_lock, &_sum](const blocked_range<int>& iter)
    {
        int sum = 0;
        for (int n = iter.begin() ; n != iter.end() ; ++n)
        {
            sum += 1 ;
        }

        _lock.lock() ;
        _sum += sum ;
        _lock.unlock() ;
    },  auto_partitioner()) ;

    printf("Result2 : %d\n", _sum) ;

    getchar() ;
    return 0;
}

'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

parallel_for문과는 달리  합산 및 정산을 할때 동기화 이슈가 없다.

각각 쓰레드 별로  body 객체가 생성이 되고  연산후

join문에서 합산되기때문이다.

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <tbb/tbb.h>


#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb;

class CSumBody
{
public:
    CSumBody()
    {
        sum_ = 0 ;
    }

    CSumBody(CSumBody &body, split)
    {
        sum_ = 0 ;
    }

    void operator()(const tbb::blocked_range<__int64> &iter)
    {
        for (__int64 n = iter.begin() ; n != iter.end() ; ++n)
        {
            sum_ += 1 ;
        }
    }

    void join(const CSumBody &body)
    {
        sum_ += body.sum_ ;
    }
public:
    __int64 sum_ ;
};



int _tmain(int argc, _TCHAR* argv[])
{

    tick_count start,stop;
    __int64 sum = 0 ;
    task_scheduler_init  init ;


    start = tick_count::now();

    CSumBody body ;
    parallel_reduce(blocked_range<__int64>(0, 1000000000), body, auto_partitioner()) ;


    stop = tick_count::now();
    printf("Result %d  \t시간 %f\n", body.sum_, (stop - start).seconds()) ;

    getchar() ;
    return 0;
}






'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

범위를 알 수 없을 때 사용하는 while문을 병렬화 시킨 로직이다.

그리고 type은 정해져 있지 않으므로 포인터를 이용하여 리스트 자료구조를  순회를 할때도 문제 없다

 

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <tbb/tbb.h>
#include <tbb/parallel_while.h>

#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb;

class CItemStream
{
public:
    CItemStream(int n) : num(n) {}

    // 여기서는 카운터 연산만 처리 해야함... 여기에서는 동기화 이슈가 없음
    bool pop_if_present(int &count)
    {
        // 언제 끝날지 모르게 하기 위해서 rand 함수를 사용
        // 실제로 count를 이용할 경우에는  if (func(num) == 0) 등등 꼴리는데로 사용!!!
        if(!(rand() % 10  != 0))
        {
            printf("루프종료...\n") ;
            return false ;
        }
        printf("Count %d\n", num) ;
        count = num ;
        num++ ;
        return true ;
    }
public:
    int num ;
};

class CBody
{
public:
    // 실제로 자료에 대한 처리는 여기서 해야 함
    void operator()(int n) const
    {
        printf("count : %d에 대한 처리 \n", n ) ;
    }
    typedef int argument_type ;
};

int _tmain(int argc, _TCHAR* argv[])
{
    srand((unsigned int)time(0)) ;
    // 아래 직렬로직을  TBB로 병렬화 루틴...
    // 단 카운트가 순서대로 처리 되지 않는다.

// int num = 0 ;
// while (rand() % 10 == 0 )
// {
// printf("count : %d에 대한 처리 \n", num ) ;
// num++ ;
// }


    parallel_while<CBody> w ;
    CItemStream stream_(0) ;
    CBody body ;

    w.run(stream_, body) ;
    printf("루프 끝\n") ;


    getchar() ;
    return 0;
}

'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

+ Recent posts