내가만든/라인들2016. 6. 30. 11:15

가중치_랜덤.zip

 

가중치에 따라 랜덤한 값이 나옴

퍼포먼스를 위하여 std::map 컨테이너를 사용 하였고, lower_bound() 를 통해 가중치로 리턴되는 값들을 얻어 올 수 있다.

단점은 가중치의 값이 추가는 되지만, 중간에 삭제는 할 수가 없다.(초기화 후에 다시 할당해서 써야한다.)

 

메르센 트위스터를 이용하여 랜덤값을 사용하였고, float을 기반으로한 실수형 가중치가 가능하며, 정수형은 특성으로 인해 맨앞의 [0]은 사용하지 않도록 예외 처리 되어 있다.

'내가만든 > 라인들' 카테고리의 다른 글

메신저 서버  (0) 2016.07.22
[Float Compare] 실수형 데이터 비교  (0) 2016.06.30
[로또 번호추출] 로또 번호  (1) 2016.04.03
[이미지 비교] 실행파일  (0) 2016.03.27
[자바] 이미지 불러오기  (1) 2016.03.11
Posted by 비엔나햄
내가만든/라인들2016. 4. 3. 17:15

로또 번호 추출기

C# 으로 제작

 

로또 추출기는 만들기 쉽다.

하지만, 일반 적인 녀석들과는 다르다. 그 차이점은 바로,

1회부터~ 696회차 까지의 당첨번호를 읽어온 뒤, 각각의 횟수를 가중치로 두어 난수를 발생 시키기 때문에 "여태까지 많이 나왔던 번호의 출현 확률이 좀더 크다."

 

이걸로 로또 대박에 도전해 봐야겠다.

 

 

로또.zip

실행파일 제공합니다:)

※주의 여기서 나온 번호로 구매해서 성공하면 본인것, 실패해도 본인것

 

+)

모바일로 제작!!!(안드로이드)

위 사진에 보이는 아이콘 클릭! 하면

위와 같은 화면이 나오는데, "대박!" 버튼을 누르면~

쨔잔~! 스레드를 이용해서 0.8~1초마다 Swap되면서 섞이는 듯한 애니메이션 처리함.

이거 구현하느라 좀 애먹었는데, 안드로이드 UI는 오직 "메인 스레드"에서만 UI표시를

변경할 수 있다... 이걸 몰라서 좀많이 헤맸고, 해결법을 찾아서 스레드에서는 UI값만 변경, 메인 스레드가 화면을 refresh 해주도록 해서 해결 했다(ㅠㅠ)

이 앱은 보통 로또 추출기와는 달리, 나눔로또에 올라온 xls 파일을 읽어 들여 여태까지 전체 당첨 되었던 데이터를 받아온다.

이를 기반으로 가장 많이 나왔던 번호 or 가장적게 나왔던 번호에 가중치를 주어 추첨할 수 있게 했다(나름 머신러닝..)

 

마지막으로 함께 만들어준 사람을 위해 Credit 페이지도 꾸며봤다.

디자이너가 UI를 잡아주니까 훨씬 보기 좋아져서 긍정적인 경험 이었다:)

 

 

이 앱으로 부자가 되었으면 좋겠다.

Lotto.zip

 

'내가만든 > 라인들' 카테고리의 다른 글

[Float Compare] 실수형 데이터 비교  (0) 2016.06.30
[가중치 랜덤] h파일과 사용 예제  (0) 2016.06.30
[이미지 비교] 실행파일  (0) 2016.03.27
[자바] 이미지 불러오기  (1) 2016.03.11
파일분할_파일  (0) 2016.03.02
Posted by 비엔나햄
내가만든/라인들2016. 3. 27. 20:24

이미지를 비교 하는 프로그램

 

비교하고자 하는 이미지 파일 2개를 선택 한 뒤 Exe Cmp클릭

 

위 그림과 같이 다른 영역은 빨간색으로 표시해준다.

감도를 설정하여 더 ㅂ미세하게, 혹은 조금 여유롭게 비교해준다.

 

이거 틀린그림 찾기 할때 유용하게 쓰일것이다(하하)

소스코드는 SVN에 커밋! 실행파일만 제공합니다:)

ImageCompare.exe

 

'내가만든 > 라인들' 카테고리의 다른 글

[가중치 랜덤] h파일과 사용 예제  (0) 2016.06.30
[로또 번호추출] 로또 번호  (1) 2016.04.03
[자바] 이미지 불러오기  (1) 2016.03.11
파일분할_파일  (0) 2016.03.02
스케쥴링_파일  (0) 2016.03.02
Posted by 비엔나햄
내가만든/라인들2016. 3. 11. 21:36
[Swing] 이미지 파일을 읽어와서 프레임에 보여주는 방법.

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class LoadImageApp extends Component {  
    //버퍼를 활용한 이미지 클래스
BufferedImage img;
 
    public void paint(Graphics g) {
        g.drawImage(img, 0, 0, null); //그림을 그리는 메소드
    }
    //디폴트 생성자
    public LoadImageApp() {
       try {
      String filename=".\\raw\\taehee1.png"; // 파일의 경로
           img = ImageIO.read(new File(filename)); //이미지 파일을 불러오는 IO 메소드
            //파일경로의 이미지 파일을 읽는다.
       } catch (IOException e) {
      e.printStackTrace();
       }
    }

    public Dimension getPreferredSize() {
        if (img == null) {
             return new Dimension(100,100); //그림 파일이 없을 경우 프레임의 크기를 100,100으로 만든다
        } else {
           return new Dimension(img.getWidth(null), img.getHeight(null)); //그림의 크기에 따라 화면의 크기를 변경한다.
       }
    }
    public static void main(String[] args) {

        JFrame f = new JFrame("Load Image Sample");
           
        f.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });

        f.add(new LoadImageApp());
        f.pack();
        f.setVisible(true);
    }
}

 

'내가만든 > 라인들' 카테고리의 다른 글

[로또 번호추출] 로또 번호  (1) 2016.04.03
[이미지 비교] 실행파일  (0) 2016.03.27
파일분할_파일  (0) 2016.03.02
스케쥴링_파일  (0) 2016.03.02
[로그분할기] 텍스트 용량별 분할기  (0) 2016.02.28
Posted by 비엔나햄
내가만든/라인들2016. 3. 2. 23:00
Posted by 비엔나햄
내가만든/라인들2016. 3. 2. 22:47

 

Sched.cpp

다운로드

Posted by 비엔나햄
내가만든/라인들2016. 2. 28. 17:19

C#

로그 파일이 일정크기(2GB)가 넘어가면 일반적인 텍스트 툴로 파일으 오픈할 수 없다..ㅠ

해서 텍스트 파일을 크기/라인 수로 분할하는 프로그램을 제작.

큰 파일은 시간이 오래 걸리기 떄문에 멀티스레드를 이용한 병렬처리를 적용해 보았다(Parallel.For)

프로세스 사용량이 전 코어 100% 사용하게 되어 일반적인 싱글 스레드 로직보다 초대 3배가량 나은 성능을 보여준다 :)

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;

namespace DistributeTextFile.FileManager
{
    // Declare ENUM Values
    //*---------------------------------*
    enum E_VALUE
    {
        KBYTE = 1024,
        MBYTE = KBYTE * KBYTE,
        READ_MAX = 100000,
    };

    enum E_TYPE
    {
        LINE = 0,
        SIZE ,
        _MAX_,
        DEFAULT = LINE,
    };
    //*---------------------------------*

    struct StreamData
    {
        public StreamReader SReader;
        public string szFilPath;
        public int nLines;
    };

    class FileManager : Util.Sigleton.Singleton<FileManager>
    {           
        public FileManager()
        {           
            this.Init();
        }
        ~FileManager() { }

        private void Init()
        {
            this.eDistributeType = E_TYPE.DEFAULT;
            this.FileListContainer = new List<string>();

            this.szDistributedTypeName = new string[(int)E_TYPE._MAX_];
            this.szDistributedTypeName[(int)E_TYPE.LINE] = "라인 수";
            this.szDistributedTypeName[(int)E_TYPE.SIZE] = "파일 크기(MB)";

            this.nDistributedTypeValue = new int[(int)E_TYPE._MAX_];
            this.nDistributedTypeValue[(int)E_TYPE.LINE] = 1000000;
            this.nDistributedTypeValue[(int)E_TYPE.SIZE] = 100;
        }

        private bool ReadFile( string szFilePath )
        {
            if (!File.Exists( szFilePath ))
            {
                return false;
            }          

            return true;
        }
       
        public void DistributeFiles()
        {
            int szMainProccessID = Thread.CurrentThread.ManagedThreadId;
            string szOutFolder = "\\Result";
            string szReadFailList = "";

            UInt64 nTotalBuffSize = 0;
            UInt64 nCurReadSize = 0;

            StreamReader []_SR = new StreamReader[this.FileListContainer.Count];
           
            List< StreamData > FileStreamContainer = new List<StreamData>();

            object objMutex = new object();
            Parallel.For(0, this.FileListContainer.Count, (nCnt) =>
            {
                if (false == this.ReadFile(this.FileListContainer[nCnt]))
                {
                    szReadFailList += this.FileListContainer[nCnt] + "; ";
                    return;
                }

                _SR[nCnt] = new StreamReader(this.FileListContainer[nCnt], Encoding.Default);
                nTotalBuffSize += (UInt64)_SR[nCnt].BaseStream.Length;

                int nLineNum = 0;

                /* 단순 라인 수 읽기는 싱글 스레드 로직이 2~3배 가량 더 빠름 */
                nLineNum = File.ReadLines(this.FileListContainer[nCnt]).Count();
                _SR[nCnt].BaseStream.Position = 0;

                StreamData stStreamData = new StreamData();
                stStreamData.nLines = nLineNum;
                stStreamData.SReader = _SR[nCnt];
                stStreamData.szFilPath = this.FileListContainer[nCnt];

                lock (objMutex)
                {
                    FileStreamContainer.Add(stStreamData);
                }
            });

            object objProgressBarMutex = new object();
            Parallel.For(0, FileStreamContainer.Count, (idx) =>
            {
                /// ---폴더 생성-------------------------------------------------
                string szPath = FileStreamContainer[idx].szFilPath;   // 파일 경로
                string szFileName = Path.GetFileName(szPath);             // 파일 이름
                string szExtName = Path.GetExtension(szFileName);        // 확장자
                szFileName = szFileName.Split('.')[0];

                string szOutPutPath = Directory.GetCurrentDirectory() + szOutFolder + "\\" + szFileName + "\\";
                Directory.CreateDirectory(szOutPutPath);
                /// ------------------------------------------------------------

                /// ---스레드 당 생성 되는 지역 변수----------------------------
                Dictionary<int, string> ReadFileContainer = new Dictionary<int, string>(); // 스레드 별로 사용할 파일(컨테이너)

                int nRemainReadLine = FileStreamContainer[idx].nLines;  // 이 스레드에서 처리해야할 총 라인 수
                int nTotalWriteLine = 0; // 현재 총 쓰기 완료 라인 수
                int nCurWriteLine = 0; // 현재 사용중인 파일에서 쓰기 완료한 라인 수
                int nFileCounts = getFileCounts(FileStreamContainer[idx].nLines); // 분할될 파일 갯수
                bool bReadStream = true; // 원본 파일(스트림) 읽기 여부
                int nReadLineNum = 0;
                /// ------------------------------------------------------------
                for (int jdx = 0; jdx < nFileCounts; jdx++)
                {
                    /// ---파일 생성-------------------------------------------------
                    FileStream FS = File.Create(szOutPutPath + szFileName + "[" + jdx + "]" + szExtName);
                    /// -------------------------------------------------------------

                    object objReadMutex = new object();
                    bool bIsWriteLineRemained = true; // 써야할 내용이 남아 있을때
                    int nCurFileTotalLines = 0; // 현재 파일에 쓰여진 라인 수

                    do
                    {
                        if (true == bReadStream)
                        {
                            /// 원본 파일에서 읽어들이기 ( 최대 100000 라인 )
                            ReadFileContainer.Clear();
                            int nLoopCnt = ((int)E_VALUE.READ_MAX < nRemainReadLine) ? (int)E_VALUE.READ_MAX : nRemainReadLine;
                            nCurWriteLine = 0; // 현재 사용중인 파일에서 쓰기 완료한 라인 수 초기화
                            Parallel.For(0, nLoopCnt, (nCurLine) =>
                            {
                                lock (objReadMutex)
                                {
                                    try
                                    {
                                        string szTmp = FileStreamContainer[idx].SReader.ReadLine();
                                        ReadFileContainer.Add(nReadLineNum++, szTmp + "\n");
                                    }
                                    catch (Exception e) { }

                                }
                            });
                        }

                        int nWriteLine = 0; // 이 반복문 내에서 쓰기 작업 완료한 횟수
                        for (int kdx = nCurWriteLine; kdx < ReadFileContainer.Count; kdx++)
                        {
                            try
                            {
                                byte[] byByteBuff = Encoding.Default.GetBytes(ReadFileContainer[kdx + nTotalWriteLine]);
                                FS.Write(byByteBuff, 0, ReadFileContainer[kdx + nTotalWriteLine].Length);

                                lock (objProgressBarMutex)
                                {
                                    // ---- Progress Bar -----------------------
                                    nCurReadSize += (UInt64)byByteBuff.Length;
                                    int nProgress = (int)(((float)nCurReadSize / (float)nTotalBuffSize) * 100);
                                    if ( Thread.CurrentThread.ManagedThreadId == szMainProccessID)
                                    {
                                        MainForm.ProgressBar_Set(nProgress);
                                    }                                   
                                    // ------------------------------------------
                                }

                            }
                            catch (Exception e)
                            {
                                nWriteLine++;
                                nCurFileTotalLines++;
                                break;
                            }
                            nWriteLine++;
                            nCurFileTotalLines++;
                            //if (nWriteLine >= this.nDistributedTypeValue[(int)this.eDistributeType])
                            //if (nCurWriteLine >= this.nDistributedTypeValue[(int)this.eDistributeType])
                            if (nCurFileTotalLines >= this.nDistributedTypeValue[(int)this.eDistributeType])
                            {
                                break;
                            }
                        }
                        /* 1. 파일 분할 조건에 따라 꽉 찼을 경우(읽어 들이는 작업은 No, 새로 파일 여는 작업 Yes)
                         * 2. 시스템 제한(10만줄)에 해당 되어 읽어 들이는 작업 재수행(읽어들이는 작업 Yes, 새로 파일 여는 작업 No) */
                        nCurWriteLine += nWriteLine;
                        nTotalWriteLine += nWriteLine;
                        nRemainReadLine -= nWriteLine; // 이 스레드(파일)의 남은 작업량을 갱신 해준다
                        if (0 >= nRemainReadLine) // 더 이상 읽어야 할 라인이 존재하지 않는다면 종료
                        {
                            bIsWriteLineRemained = false;
                            FS.Close();
                        }
                        else // 아직 읽어야 할 라인이 존재한다
                        {
                            // 1. 파일 분할 조건에 해당하지 않으면( 컨테이너 내용은 다썼는데, 파일 제한에 해당 되지 않음) 컨테이너를 다시 채우고 쓰기작업
                            // do~while문 탈출 하지 않고 재수행
                            if (nCurWriteLine == ReadFileContainer.Count && nTotalWriteLine < this.nDistributedTypeValue[(int)this.eDistributeType])
                            {
                                bReadStream = true;
                                continue;
                            }
                            // 2. 파일 분할 조건에 해당하고, 컨테이너 내용도 다썼을 경우
                            // do~while문 탈출
                            else if (nCurWriteLine == ReadFileContainer.Count && nTotalWriteLine >= this.nDistributedTypeValue[(int)this.eDistributeType])
                            {
                                bReadStream = true;
                                bIsWriteLineRemained = false;
                                FS.Close();
                            }
                            // 3. 파일 분할 조건에 해당하면( 컨테이너 내용 다 못썼는데, 파일 제한에 해당됨) 파일을 새로 생성(컨테이너 비우기는 X)
                            // do~while문 탈출
                            else
                            {
                                bReadStream = false;
                                bIsWriteLineRemained = false;
                                FS.Close();
                            }
                        }

                    } while (bIsWriteLineRemained);
                }
            }
            );

            OpenFolder(Directory.GetCurrentDirectory() + szOutFolder);
            MainForm.ProgressBar_Init();

            // =======================================================================
            // =======================================================================
        }

        private int getFileCounts(int nLineNums)
        {
            int nFileNum = 0;

            nFileNum = (nLineNums / this.nDistributedTypeValue[(int)this.eDistributeType]);
            if (0 < nLineNums % this.nDistributedTypeValue[(int)this.eDistributeType]) { nFileNum++; }

            return nFileNum;
        }
        private bool checkConditions( UInt64 dwReadValue )
        {
            int nType = (int)this.eDistributeType;
            UInt64 dwCondition = (UInt64) this.nDistributedTypeValue[nType];
            bool retValue = true;
            switch (this.eDistributeType)
            {
                case E_TYPE.LINE:
                default:
                    {
                        if (dwCondition <= dwReadValue)
                        {
                            retValue = false;
                        }
                    }
                    break;
                case E_TYPE.SIZE:
                    {
                        if (dwCondition * (UInt64)E_VALUE.MBYTE <= dwReadValue)
                        {
                            retValue = false;
                        }
                    }
                    break;
            }
            return retValue;
        }
        public void OpenFolder( string szFolderPath )
        {
            System.Diagnostics.Process.Start("explorer.exe", szFolderPath);
        }

        public void SetFilePath(string szFilePath)
        {
            this.szFilePath = szFilePath;
        }
        public void SetFilePath(string []szFilePath)
        {
            this.FileListContainer.Clear();
            this.FileListContainer.AddRange(szFilePath);
        }
        public String GetFilePath()
        {
            return this.szFilePath;
        }

        public void SetType(int nType)
        {
            this.eDistributeType = (E_TYPE)nType;
        }
        public new int GetType()
        {
            E_TYPE eIdx = this.eDistributeType;
            return (int)eIdx;
        }
        public String[] GetTypes()
        {
            return this.szDistributedTypeName;
        }

        public void SetTypeValue(int nValue)
        {
            this.nDistributedTypeValue[(int)this.eDistributeType] = nValue;
        }
        public int GetTypeValue()
        {
            return this.nDistributedTypeValue[(int)this.eDistributeType];
        }

        public void SetMainForm(DistributeTextFile.Form1 stMainForm) { this.MainForm = stMainForm; }

        private string szFilePath;
        private List<string> FileListContainer;
        private E_TYPE eDistributeType;
        private String []szDistributedTypeName;
        private int []nDistributedTypeValue;
               
        ///  Main Form
        private DistributeTextFile.Form1 MainForm;
    }
}

※ 성능을 더 개선한 버전(컨테이너 사용하지 않음)도 있는데, 모든 소스는 SVN에 있다 :)

※ 사용 예시

 

 

 

 

'내가만든 > 라인들' 카테고리의 다른 글

파일분할_파일  (0) 2016.03.02
스케쥴링_파일  (0) 2016.03.02
[이벤트] 카카오톡 욕설 집계 스크립트  (0) 2016.02.28
[이벤트] 크리스마스 트리  (0) 2016.02.28
[메모리풀] 헤더 파일  (0) 2016.02.28
Posted by 비엔나햄
내가만든/라인들2016. 2. 28. 17:11

Python V3.5

카카오톡 대화 욕설 집계 V1.0.0

카카오톡 대화내용을 내보내기 한 뒤, 나온 파일을 통해 욕 횟수를 집계해 준다.

#read.py

import string

#def ExportText()
def ExportText(append):
 f = open("C:\\PythonStudy\\ChatData\\Parsing_Chat.csv", 'a') 
 f.write(append)
 f.close()
 
#def ReadText()
def ReadText( MalWord ):
 
 # 대화 목록 읽어 오기
 f = open("C:\\PythonStudy\\ChatData\\KakaoTalkChats.txt", 'r') 
 Curline = f.readline()
 
 #While Loop1========================================================
 while Curline:
  line = Curline
  NextLine = f.readline()
  
 #While Loop2--------------------------------------------------------
  while NextLine:
   if 1 >= len(NextLine) : # 줄바꿈만 있는 공백
    line = NextLine
    NextLine = f.readline()
   
   if '2' == NextLine[0] and '년' == NextLine[4] : # 기본 채팅 라인
    break
   
   line = line.split('\n')[0]
   line += NextLine   
   NextLine = f.readline()
 #-------------------------------------------------------- 
  
 #========================================================
  for FilterWord in MalWord: # 필터 단어 수 만큼 검사 하기 때문에, 중복 여부를 설정해야 한다.
   nRet = line.find(FilterWord)
   if -1 == nRet: 
    continue
    
   split_SemiColumn = line.split(' : ')
   if 2 > len(split_SemiColumn):
    continue
   
   try: # 콜론(:)으로 파싱 시도
    split_Comma = split_SemiColumn[0].split(',')
    
   except: # 예외 사항 발생시 넘어감
    continue
           
   if 10 < len(split_Comma[1]): #이름 파싱
    continue
       
   #시간 + 이름 + 내용
   strLine = split_Comma[0]
   strLine += "," +split_Comma[1]
   strLine += "," +FilterWord
   strLine += "," +split_SemiColumn[1]
   ExportText( strLine )
   break # break 가 있으면 중복 제거, 없으면 중복 허용
   
  Curline = NextLine
  
 f.close()
 
#def ReadMalWord()
def ReadMalWord():
 f = open("C:\\PythonStudy\\MalWord\\MalWord.txt", 'r')
 line = f.read().splitlines()
 Container = []
 
 for MalWord in line:
  Container.append(MalWord)
    
 f.close()
 
 return Container

#main

WordContainer = ReadMalWord() # 필터링 단어 리스트

ReadText(WordContainer) # 대화 목록 읽어오기

 

파이썬은 기본 코딩 문법과는 다른 양상이어서 이해가 조금 힘들었다.

탭한번만 잘못써도 Scope가 바뀌어 버리는 상황이 발생! 주의해야 한다(적절한 코드 편집기 사용이 필 수 인 것 같다. 난 NotePad++ 써서 어려웠음)

사용하려면 필터링 대상 단어를 입력 해야하는데, 저작권 무제로 배포 못합니다(__)

프로그램 사용해보고 싶으시면, 실행파일로 만들어 드립니다 :)

(사용예시)

 

 

스크립트를 통해 집계된 욕 획수를 엑셀로 정리하여 표나 차트로 제공하면 더욱 좋다 ㅋㅋ :)

 

 

'내가만든 > 라인들' 카테고리의 다른 글

스케쥴링_파일  (0) 2016.03.02
[로그분할기] 텍스트 용량별 분할기  (0) 2016.02.28
[이벤트] 크리스마스 트리  (0) 2016.02.28
[메모리풀] 헤더 파일  (0) 2016.02.28
[채팅] 클라이언트 코드  (0) 2016.02.28
Posted by 비엔나햄
내가만든/라인들2016. 2. 28. 16:54

크리스마스에 여자친구에게 주고자 만들어봄.

이 간단한 녀석이 이틀이나 걸렸다..ㅠㅠ

그래도 벡터와 알림 시스템, 그리고 멀티스레드를 이용하여 나름 구조적으로 설계한,

애정 가득한 프로그램이다(소리도 난다) :)

매년 써먹어야지ㅋㅋ

 

Tree.7z

 

 

Posted by 비엔나햄
내가만든/라인들2016. 2. 28. 16:47

C/C++

메모리풀 포인터 구현 버전

메모리풀을 포인터와 벡터로 구현해 보았는데,

벡터는 너무 간단하여 포인터로 직접 구현한 뒤, 범용적으로 사용하기 위해 템플릿 적용.

메모리풀을 사용하면 할당하는데에 작은 시간비용이 추가 되긴 하지만,

leak방지와 메모리 관리에 효율 적이다.

자세한 내용은 SVN에 :)

template< class Type, int nSize >
class Pool
{
private:
 struct Node
 {
  Type clsItem;

  Node * pNext;
 };

public: 
 Pool();
 ~Pool(){}

 int GetPoolSize()
 { return this->m_nPoolSize; }

 int GetMaxCount()
 { return this->m_nMaxCount; }

 int GetUsedCount()
 { return this->m_nUsedCount; }
public:
 Type*    Capture();
 void    Release(); // Test
 void    Release( Type * pItem );

private:
 int m_nPoolSize; // 메모리 풀 사이즈
 int m_nUsedCount; // 사용 중인 객체 갯수
 int m_nMaxCount; // 메모리 풀에 보유중인 객체 전체 갯수

 Node * m_pVacant; // 사용 가능 객체 모음 포인터
 Node * m_pOccupied; // 사용 중인 객체 모음 포인터
};

template< class Type, int nSize >
Pool<Type, nSize>::Pool()
{
 m_nPoolSize  = sizeof(*this);
 m_nUsedCount = 0;
 m_nMaxCount  = 0;

 m_pVacant  = nullptr;
 m_pOccupied  = nullptr;
 
 for( int i = 0; i < nSize; i++ )
 {
  Node * pNewNode = new Node();

  m_nPoolSize += sizeof(Type); // 생성한 노드 만큼 풀 사이즈 증가
  m_nMaxCount += 1;    // 전체 객체 갯수 증가

  if( nullptr == m_pVacant )
  {   
   pNewNode->pNext = nullptr;
   m_pVacant = pNewNode;
   continue;
  }
  
  pNewNode->pNext = m_pVacant->pNext;
  m_pVacant->pNext = pNewNode;
 }
}

template< class Type, int nSize >
Type*
Pool<Type, nSize>::Capture()
{
 Node * pNode = m_pVacant;
 if( nullptr != pNode ) // 풀에 비어있는 노드가 있다면
 {
  m_pVacant = pNode->pNext;
 }
 else // 비어있는 노드가 없다면
 {
  pNode = new Node();

  m_nPoolSize += sizeof(Type);
  m_nMaxCount += 1;
 }
 
 // 사용중 객체 리스트에 넣는다
 pNode->pNext = m_pOccupied;
 m_pOccupied  = pNode;
  
 m_nUsedCount += 1;
 
 return &(pNode->clsItem);
}

template< class Type, int nSize >
void
Pool<Type, nSize>::Release() /* TEST (맨 앞 노드 해제) */
{
 if( nullptr == m_pOccupied )
 {
  return;
 }

 Node * pReleaseNode = m_pOccupied;
 m_pOccupied = pReleaseNode->pNext;

 // 미사용 객체 리스트에 넣는다
 pReleaseNode->pNext = m_pVacant;
 m_pVacant = pReleaseNode;
 
 m_nUsedCount -= 1;
}

template< class Type, int nSize >
void
Pool<Type, nSize>::Release( Type * pItem )
{
 if( nullptr == pItem )
 {
  return;
 }

 bool bIsExist = false;
 Node * pPrevNode = nullptr;
 Node * pCurNode = m_pOccupied;
 for( pCurNode; /* 사용중인 객체를 순회 한다 */
   nullptr != pCurNode;
   pCurNode = pCurNode->pNext )
 {
  if( pItem == &(pCurNode->clsItem) )
  {
   bIsExist = true;
  }
  pPrevNode = pCurNode;
 }

 if( false == bIsExist ) // 사용중인 객체가 없다
 {
  return;
 }

 // 노드가 존재하는데 이전의 노드가 null이라면, 첫번째 노드이다
 if( nullptr == pPrevNode )
 {
  m_pOccupied = pCurNode->pNext;
 }
 else
 {
  pPrevNode->pNext = pCurNode->pNext;
 }

 m_nUsedCount -= 1; // 사용중인 객체의 수를 감소 시킨다
 
 // 미사용 객체 리스트에 넣는다
 pCurNode->pNext = m_pVacant;
 m_pVacant = pCurNode;

 m_nUsedCount -= 1;
}

Posted by 비엔나햄